SURFEX v8.1
General documentation of Surfex
faxion.F90
Go to the documentation of this file.
1 ! Oct-2012 P. Marguinaud 64b LFI
2 ! Jan-2011 P. Marguinaud Thread-safe FA
3 SUBROUTINE faxion_fort &
4 & (fa, pchame, kpuiss, kdimnc, klcham, pmin, &
5 & pmax, knbits, ldarpe, pecart, ldmlam, &
6 & knozpa, kstrof, ktronc, kxlopa )
7 USE fa_mod, ONLY : fa_com
8 USE parkind1, ONLY : jprb
9 USE yomhook , ONLY : lhook, dr_hook
10 USE lfi_precision
11 IMPLICIT NONE
12 !****
13 ! Sous-programme INTERNE du logiciel de Fichiers ARPEGE:
14 ! calcul de l'erreur totale par le codage GRIB
15 ! sur un champ en coefficients spectraux, en mode "complex packing".
16 !**
17 ! Arguments :
18 ! ( Tableau ) PCHAME (Entree) ==> Champ en coef. spectraux en entree;
19 ! KPUISS (Entree) ==> Puissance de laplacien a utiliser;
20 ! KDIMNC (Entree) ==> Taille de la zone non codee;
21 ! KLCHAM (Entree) ==> Longueur totale du champ en c.spx.;
22 ! PMIN (Entree) ==> Minimum precalcule du champ module;
23 ! PMAX (Entree) ==> Maximum " " " " ;
24 ! KNBITS (Entree) ==> Nombre de bits par valeur a coder;
25 ! LDARPE (Entree) ==> Vrai si GRIB non standard;
26 ! PECART (Sortie) ==> Erreur relative maximum commise,
27 ! en valeur absolue;
28 ! LDMLAM (Entree) ==> Vrai si fichier aladin
29 ! (Tableau) KNOZPA (Entree) ==> Nombre d'onde zonal maxi par parallele;
30 ! (du pole nord vers l'equateur seulement)
31 ! KSTROF (Entree) ==> Sous-troncature non compactee EFFECTIVE (coef. spectraux)
32 ! KTRONC (Entree) ==> Troncature (NS pour Aladin)
33 ! KXLOPA (Entree) ==> Nombre maximum de longitudes par cercle de latitudes
34 !
35 ! Modifications
36 ! -------------
37 !
38 ! Juillet 1998, J. Clochard, SCEM/TTI/DAO:
39 !
40 ! -Le critere a minimiser est mis sous la forme de fonctions
41 ! -Pour le cas LDARPE=.TRUE., utilisation des memes gardes-fous
42 ! que dans CODEGA.
43 !
44 ! Septem. 2000, D. Paradis, SCEM/TTI/DEV:
45 !
46 ! -Ajustement de la puissance Dolby pour des nb d'onde (JN)
47 ! uniquement inferieurs a MIN(FA%MTRONC(),(FA%NXLOPA()-1)/3): on
48 ! s'affranchit de l'influence des grands nb d'onde sur des
49 ! grilles lineaires pour le choix du Dolby.
50 !
51 ! Mars 2003, R. El Khatib CNRM/GMAP:
52 !
53 ! -Optimisation : ISAMAX remplace par MAXLOC
54 !
55 ! March 2010: J. Masek - fix of precomputed optimal Laplacian power
56 !
57 !
58 TYPE(fa_com) :: FA
59 INTEGER (KIND=JPLIKB) KPUISS, KDIMNC, KLCHAM, KNBITS, KSTROF
60 INTEGER (KIND=JPLIKB) KTRONC, KXLOPA
61 !
62 INTEGER (KIND=JPLIKB) KNOZPA (fa%jpxind)
63 !
64 REAL (KIND=JPDBLR) PMIN, PMAX, PECART
65 REAL (KIND=JPDBLR) PCHAME(klcham)
66 REAL (KIND=JPDBLR) ZERR (klcham)
67 REAL (KIND=JPDBLR) ZECART_LOC
68 !
69 LOGICAL LDARPE, LDMLAM
70 !
71 INTEGER (KIND=JPLIKB) JN, JIND, ISCALE, J
72 INTEGER (KIND=JPLIKB) INDICE, IPUISX, IOFF, IM
73 INTEGER (KIND=JPLIKB) INDLAP, IRAPOR, IPUISR
74 INTEGER (KIND=JPLIKB) IMLIM, IEXP, IMANT, IPUIS2
75 INTEGER (KIND=JPLIKB) IDEB, IFIN, ITRDOL, ILCHADO
76 INTEGER (KIND=JPLIKB) IEXP32, IMANT32
77 !
78 REAL (KIND=JPDBLR) ZREFER, ZDIFFR, ZCOMPA, ZAUXI1, ZAUXI2, ZS
79 
80 REAL(KIND=JPRB) :: ZHOOK_HANDLE
81 
82 IF (lhook) CALL dr_hook('FAXION_MT',0,zhook_handle)
83 !**
84 ! 0. - INITIALISATIONS FAITES AU PREMIER APPEL DU SOUS-PROGRAMME.
85 !-----------------------------------------------------------------------
86 !
87 IF (fa%FAXION_LLPREA) THEN
88  fa%FAXION_ZEPSIL=tiny(fa%FAXION_ZEPSIL)
89  fa%FAXION_ISCALX=99
90  fa%FAXION_LLPREA=.false.
91 ENDIF
92 !**
93 ! 1. - CALCUL DIRECT, EN ESSAYANT DE MINIMISER LES OPERATIONS.
94 ! ( a l'aide des puissances precalculees dans FA%XLAP2D )
95 !-----------------------------------------------------------------------
96 !
97 IF (ldarpe) THEN
98 !
99  zdiffr=pmax-pmin
100 !
101  IF ( zdiffr .LE. fa%FAXION_ZEPSIL ) THEN
102  zauxi1=min( abs(pmin), abs(pmax) )
103  IF ( zauxi1 .LE. fa%FAXION_ZEPSIL ) zauxi1=0._jpdblr
104  pmax=sign(zauxi1,pmax)
105  pmin=pmax
106  zauxi1=0._jpdblr
107  zauxi2=0._jpdblr
108  ELSE
109  zcompa=real(2**knbits-1, jpdblr)
110  zauxi1=zcompa/zdiffr
111  zauxi2=zdiffr/zcompa
112  ENDIF
113 !
114  zrefer=pmin
115 !
116 ELSE
117 !
118  CALL confi (pmin,iexp32,imant32,zrefer)
119  iexp=iexp32
120  imant=imant32
121 
122  zs = (pmax-zrefer)/(2**(knbits+1)-1)
123  zauxi1=1._jpdblr
124  zauxi2=2._jpdblr
125  IF (zs.NE.0._jpdblr) zs = log(zs)/log(zauxi2) + zauxi2
126  iscale = min(int(zs,jplikb), &
127 & int(zs+sign(zauxi1,zs),jplikb))
128  iscale = max(-fa%FAXION_ISCALX,min(fa%FAXION_ISCALX,iscale))
129  zauxi1 = zauxi2**(-iscale)
130  zauxi2 = zauxi2**iscale
131 !
132 ENDIF
133 !
134 ! Calcul de la borne superieure de la plage des nb d'onde
135 ! servant pour l'ajustement du Dolby (borne inferieure=KSTROF)
136 ! valable uniquement dans le cas Arpege pour ne pas prendre
137 ! en compte les coeff spectraux relatifs aux nb d'onde non
138 ! quadratiques (grille lineaire).
139 !
140 IF (ldarpe.AND..NOT.ldmlam) THEN
141  itrdol = min( ktronc , (kxlopa-1)/3 )
142  ilchado = (itrdol+1)**2
143 ENDIF
144 !
145 IF (kpuiss.EQ.0) THEN
146 !
147  IF (ldmlam) THEN
148 !$OMP PARALLEL DO PRIVATE(JN,JIND) IF(FA%LOPENMP)
149  DO jn=0,ktronc
150  DO jind=knozpa(2*jn+3),knozpa(2*jn+4)
151  zerr(jind)=zcrit0(jind)
152  ENDDO
153  ENDDO
154 !$OMP END PARALLEL DO
155  ELSE
156  DO j=kdimnc+1,ilchado
157  zerr(j)=zcrit0(j)
158  ENDDO
159  ENDIF
160 !
161 ELSE
162  ipuisx=abs(kpuiss)
163 !
164  IF (kpuiss.GT.0) THEN
165  indice=1
166  ELSE
167  indice=0
168  ENDIF
169 !
170  IF (ipuisx.LE.fa%JPUILA) THEN
171 !
172 ! Dans ce cas precis, on pourrait aussi remplacer la division
173 ! par ZCOEFF par une multiplication par FA%XLAP2D(J,IPUISX,1-INDICE).
174 ! Il y aurait gain en calcul, mais reference memoire supplementaire.
175 !
176  IF (ldmlam) THEN
177 #ifndef RS6K
178 !$OMP PARALLEL DO PRIVATE(JN,JIND,IOFF,IM,INDLAP) &
179 !$OMP& IF(FA%LOPENMP)
180 #endif
181  DO jn=1,ktronc
182  DO jind=knozpa(2*jn+3)+4,knozpa(2*jn+4)
183  ioff=jind-knozpa(2*jn+3)
184  im=ioff/4
185  indlap=((jn-1)*fa%JPXTRO)+im
186  zerr(jind)=zcritr(jind,fa%XLAP2DA(indlap,ipuisx,indice))
187  ENDDO
188  ENDDO
189 #ifndef RS6K
190 !$OMP END PARALLEL DO
191 #endif
192  ELSE
193  DO j=kdimnc+1,ilchado
194  zerr(j)=zcritr(j,fa%XLAP2D(j,ipuisx,indice))
195  ENDDO
196  ENDIF
197 !
198  ELSEIF (ipuisx.LE.2*fa%JPUILA) THEN
199  ipuis2=ipuisx/2
200 !
201  IF (ipuisx.EQ.2*ipuis2) THEN
202 !
203  IF (ldmlam) THEN
204 #ifndef RS6K
205 !$OMP PARALLEL DO PRIVATE(JN,JIND,IOFF,IM,INDLAP) &
206 !$OMP& IF(FA%LOPENMP)
207 #endif
208  DO jn=1,ktronc
209  DO jind=knozpa(2*jn+3)+4,knozpa(2*jn+4)
210  ioff=jind-knozpa(2*jn+3)
211  im=ioff/4
212  indlap=((jn-1)*fa%JPXTRO)+im
213  zerr(jind)=zcritr(jind, &
214 & fa%XLAP2DA(indlap,ipuis2,indice)**2)
215  ENDDO
216  ENDDO
217 #ifndef RS6K
218 !$OMP END PARALLEL DO
219 #endif
220  ELSE
221  DO j=kdimnc+1,ilchado
222  zerr(j)=zcritr(j,fa%XLAP2D(j,ipuis2,indice)**2)
223  ENDDO
224  ENDIF
225 !
226  ELSE
227 !
228  IF (ldmlam) THEN
229 #ifndef RS6K
230 !$OMP PARALLEL DO PRIVATE(JN,JIND,IOFF,IM,INDLAP) &
231 !$OMP& IF(FA%LOPENMP)
232 #endif
233  DO jn=1,ktronc
234  DO jind=knozpa(2*jn+3)+4,knozpa(2*jn+4)
235  ioff=jind-knozpa(2*jn+3)
236  im=ioff/4
237  indlap=((jn-1)*fa%JPXTRO)+im
238  zerr(jind)=zcritr(jind,fa%XLAP2DA(indlap,fa%JPUILA,indice) &
239 & *fa%XLAP2DA(indlap,ipuisx-fa%JPUILA,indice))
240  ENDDO
241  ENDDO
242 #ifndef RS6K
243 !$OMP END PARALLEL DO
244 #endif
245  ELSE
246  DO j=kdimnc+1,ilchado
247  zerr(j)=zcritr(j,fa%XLAP2D(j,fa%JPUILA,indice) &
248 & *fa%XLAP2D(j,ipuisx-fa%JPUILA,indice))
249  ENDDO
250  ENDIF
251 !
252  ENDIF
253 !
254  ELSE
255  irapor=1+(ipuisx-1)/fa%JPUILA
256  ipuisr=ipuisx/irapor
257 !
258  IF (ipuisx.EQ.irapor*ipuisr) THEN
259 !
260  IF (ldmlam) THEN
261 #ifndef RS6K
262 !$OMP PARALLEL DO PRIVATE(JN,JIND,IOFF,IM,INDLAP) &
263 !$OMP& IF(FA%LOPENMP)
264 #endif
265  DO jn=1,ktronc
266  DO jind=knozpa(2*jn+3)+4,knozpa(2*jn+4)
267  ioff=jind-knozpa(2*jn+3)
268  im=ioff/4
269  indlap=((jn-1)*fa%JPXTRO)+im
270  zerr(jind)=zcritr(jind, &
271 & fa%XLAP2DA(indlap,ipuisr,indice)**irapor)
272  ENDDO
273  ENDDO
274 #ifndef RS6K
275 !$OMP END PARALLEL DO
276 #endif
277  ELSE
278  DO j=kdimnc+1,ilchado
279  zerr(j)=zcritr(j,fa%XLAP2D(j,ipuisr,indice)**irapor)
280  ENDDO
281  ENDIF
282 !
283  ELSE
284 !
285  IF (ldmlam) THEN
286 #ifndef RS6K
287 !$OMP PARALLEL DO PRIVATE(JN,JIND,IOFF,IM,INDLAP) &
288 !$OMP& IF(FA%LOPENMP)
289 #endif
290  DO jn=1,ktronc
291  DO jind=knozpa(2*jn+3)+4,knozpa(2*jn+4)
292  ioff=jind-knozpa(2*jn+3)
293  im=ioff/4
294  indlap=((jn-1)*fa%JPXTRO)+im
295  zerr(jind)=zcritr(jind, &
296 & fa%XLAP2DA(indlap,fa%JPUILA,indice)**(irapor-1) &
297 & *fa%XLAP2DA(indlap,ipuisx-fa%JPUILA*(irapor-1),indice))
298  ENDDO
299  ENDDO
300 #ifndef RS6K
301 !$OMP END PARALLEL DO
302 #endif
303  ELSE
304  DO j=kdimnc+1,ilchado
305  zerr(j)=zcritr(j, &
306 & fa%XLAP2D(j,fa%JPUILA,indice)**(irapor-1) &
307 & *fa%XLAP2D(j,ipuisx-fa%JPUILA*(irapor-1),indice))
308  ENDDO
309  ENDIF
310 !
311  ENDIF
312 !
313  ENDIF
314 !
315 ENDIF
316 !
317 pecart=0._jpdblr
318 IF (ldmlam) THEN
319 !$OMP PARALLEL IF(FA%LOPENMP) &
320 !$OMP& PRIVATE(JN,IMLIM,IDEB,IFIN,JIND,ZECART_LOC) &
321 !$OMP& REDUCTION(+:PECART)
322 !$OMP DO
323  DO jn=1,ktronc
324  imlim=kstrof-jn
325  ideb=max(knozpa(2*jn+3)+4,knozpa(2*jn+3)+4*(1+imlim))
326  ifin=knozpa(2*jn+4)
327  zecart_loc=0._jpdblr
328  DO jind=ideb,ifin
329  zecart_loc=zecart_loc+zerr(jind)
330  ENDDO
331  pecart=pecart+zecart_loc
332 !
333  ENDDO
334 !$OMP END DO
335 !$OMP END PARALLEL
336 ELSE
337  DO j=kdimnc+1,ilchado
338  pecart=pecart+zerr(j)
339  ENDDO
340 ENDIF
341 !
342 IF (fa%LFAMOP) THEN
343  IF (ldarpe.AND..NOT.ldmlam) THEN
344  WRITE (unit=fa%NULOUT,fmt=*) &
345 & 'FAXION: KPUISS=', kpuiss,', KDIMNC=',kdimnc, &
346 & ', KLCHAM=', klcham, ', ITRDOL=', itrdol, ', ILCHADO=', &
347 & ilchado, ', PMIN=', pmin, ', PMAX=', pmax
348  ELSE
349  WRITE (unit=fa%NULOUT,fmt=*) &
350 & 'FAXION: KPUISS=', kpuiss,', KDIMNC=',kdimnc, &
351 & ', KLCHAM=', klcham, &
352 & ', PMIN=', pmin, ', PMAX=', pmax
353  ENDIF
354  WRITE (unit=fa%NULOUT,fmt=*)'FAXION: PECART=', pecart
355 ENDIF
356 !
357 IF (lhook) CALL dr_hook('FAXION_MT',1,zhook_handle)
358 
359 CONTAINS
360 
361 REAL (KIND=JPDBLR) FUNCTION zypr (IZZZZZ, ZCOEFF)
362 INTEGER (KIND=JPLIKB) :: IZZZZZ
363 REAL (KIND=JPDBLR) :: ZCOEFF
364 zypr = zrefer + zauxi2 * anint(zauxi1 * (pchame(izzzzz)/zcoeff - zrefer))
365 END FUNCTION
366 
367 REAL (KIND=JPDBLR) FUNCTION zyp0 (IZZZZZ)
368 INTEGER (KIND=JPLIKB) :: IZZZZZ
369 zyp0 = zrefer + zauxi2 * anint(zauxi1 * (pchame(izzzzz) - zrefer))
370 END FUNCTION
371 
372 !
373 ! Fonction "critere" a minimiser lorsque la modulation de la
374 ! puissance de laplacien est possible.
375 !
376 REAL (KIND=JPDBLR) FUNCTION zcritr (IZZZZZ, ZCOEFF)
377 INTEGER (KIND=JPLIKB) :: IZZZZZ
378 REAL (KIND=JPDBLR) :: ZCOEFF
379 zcritr = (zypr(izzzzz,zcoeff)*zcoeff - pchame(izzzzz))**2
380 END FUNCTION
381 
382 !
383 ! Meme chose, mais pour la puissance 0.
384 !
385 REAL (KIND=JPDBLR) FUNCTION zcrit0 (IZZZZZ)
386 INTEGER (KIND=JPLIKB) :: IZZZZZ
387 zcrit0 = (zyp0(izzzzz) - pchame(izzzzz))**2
388 END FUNCTION
389 
390 END SUBROUTINE
391 
392 !INTF PCHAME IN DIMS=KLCHAM
393 !INTF KPUISS IN
394 !INTF KDIMNC IN
395 !INTF KLCHAM IN
396 !INTF PMIN IN
397 !INTF PMAX IN
398 !INTF KNBITS IN
399 !INTF LDARPE IN
400 !INTF PECART OUT
401 !INTF LDMLAM IN
402 !INTF KNOZPA IN DIMS=FA%JPXIND
403 !INTF KSTROF IN
404 !INTF KTRONC IN
405 !INTF KXLOPA IN
integer, parameter jplikb
real(kind=jpdblr) function zcritr(IZZZZZ, ZCOEFF)
Definition: faxion.F90:377
subroutine confi(PFVAL, KEXP, KMANT, PNFVAL)
Definition: confi.F:2
Definition: fa_mod.F90:1
integer, parameter jprb
Definition: parkind1.F90:32
real(kind=jpdblr) function zypr(IZZZZZ, ZCOEFF)
Definition: faxion.F90:362
integer, parameter jpdblr
subroutine faxion_fort(FA, PCHAME, KPUISS, KDIMNC, KLCHAM, PMIN, PMAX, KNBITS, LDARPE, PECART, LDMLAM, KNOZPA, KSTROF, KTRONC, KXLOPA)
Definition: faxion.F90:7
real(kind=jpdblr) function zcrit0(IZZZZZ)
Definition: faxion.F90:386
logical lhook
Definition: yomhook.F90:15
real(kind=jpdblr) function zyp0(IZZZZZ)
Definition: faxion.F90:368
real8 real
Definition: privpub.h:396