source: trunk/divfred.pro @ 48

Last change on this file since 48 was 48, checked in by pinsard, 10 years ago

fix thanks to coding rules

File size: 14.1 KB
Line 
1;+
2;
3; @file_comments
4; calcule la divergence d'un champ 2D
5;
6; @categories
7; matrix
8;
9; @examples
10; IDL> res=divfred(u,v)
11;
12; @param uu {in}{required}{type=2D array}
13; Matrix representing the zonal coordinates (U point)
14;
15; @param vv {in}{required}{type=2D array}
16; Matrix representing the zonal coordinates (V point)
17;
18; @returns
19; the divergence of the input data (with the same size)
20;
21; @uses
22; <pro>common</pro>
23;
24; @restrictions
25; - Requires SAXO tools
26; - les matrices u et v peuvent de 2 a 4 dimensions.
27; attention pour distinguer les différentes configurations de u et v
28; (xy, xyz, xyt, xyzt), on regarde la variable du common
29;        -time qui contient le calendrier en jour julien d''IDL auquel
30;        se rapportent u et v ansi que la variable
31;        -jpt qui est le nombre de pas de temps à considérer dans time.
32; les tableaux u et v sont découpés sur le même domaine
33; géographique. A cause du décalage des grilles T, U, V et F il est
34; possible que ces 2 tableaux n''aient pas la même taille et se
35; reportent à des indices différents. Si tel est le cas les tableaux
36; sont redécoupés sur les indices qu'ils ont en commun et le dommaine
37; est redéfini pour qu'il colle à ces indices communs.
38; pour éviter ces redécoupes utiliser le mot clé /memeindice dans
39; <pro>domdef</pro>
40;
41; les points sur le bord du dessin sont mis à !values.f_nan
42;
43; @todo
44; ++ pas fini de comprendre, tester (compatibilité saxo), adapter, commenter
45; nettoyer
46; ++ a comparer et merger avec SAXO_DIR/ToBeReviewed/CALCULS/div.pro
47;       Written by:   fplod 2006-03-27T13:45:14Z aedon.lodyc.jussieu.fr (Darwin)
48;
49; @history
50; fplod 2007-07-30T10:11:33Z aedon.locean-ipsl.upmc.fr (Darwin)
51; add header for idldoc
52; created from
53; /usr/work/sur/fvi/OPA/geomag/divfred.pro
54; Guillaume Roullet (grlod\@ipsl.jussieu.fr)
55;                      Creation : printemps 1998
56;                      Sebastien Masson (smasson\@lodyc.jussieu.fr)
57;                      adaptation pour marcher avec un domaine reduit
58;                      12/1/2000
59; @version
60; $Id$
61;
62;-
63;
64FUNCTION divfred, uu, vv
65   tempsun = systime(1)         ; pour key_performance
66@common
67   u = uu
68   v = vv
69
70   date1 = time[0]
71   if n_elements(jpt) EQ 0 then date2 = date1 ELSE date2 = time[jpt-1]
72   if (size(u))[0] NE (size(v))[0] then return,  -1
73
74;------------------------------------------------------------
75; on trouve les points que u et v ont en communs
76;------------------------------------------------------------
77   indicexu = (lindgen(jpi))[firstxu:firstxu+nxu-1]
78   indicexv = (lindgen(jpi))[firstxv:firstxv+nxv-1]
79   indicex = inter(indicexu, indicexv)
80   indiceyu = (lindgen(jpj))[firstyu:firstyu+nyu-1]
81   indiceyv = (lindgen(jpj))[firstyv:firstyv+nyv-1]
82   indicey = inter(indiceyu, indiceyv)
83   nx = n_elements(indicex)
84   ny = n_elements(indicey)
85   indice2d = lindgen(jpi, jpj)
86   indice2d = indice2d[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1]
87   case 1 of
88;----------------------------------------------------------------------------
89;----------------------------------------------------------------------------
90;xyz
91;----------------------------------------------------------------------------
92      (size(u))[0] EQ 3 AND date1 EQ date2 :BEGIN
93;------------------------------------------------------------
94; extraction de u et v sur le domaine qui convient
95;------------------------------------------------------------
96         case 1 of
97            (size(u))[0] NE 3 OR (size(v))[0] NE 3: return,  -1
98            (size(u))[1] EQ nxu AND (size(u))[2] EQ nyu AND $
99             (size(v))[1] EQ nxv AND (size(v))[2] EQ nyv:BEGIN
100               case 1 of
101                  nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *, *] ELSE u = u[1: nx, *, *]
102                  nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *, *] ELSE v = v[1: nx, *, *]
103                  nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1, *] ELSE u = u[*, 1: ny, *]
104                  nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1, *] ELSE v = v[*, 1: ny, *]
105                  ELSE :
106               endcase
107            END
108            (size(u))[1] EQ jpi AND (size(u))[2] EQ jpj AND $
109             (size(v))[1] EQ jpi AND (size(v))[2] EQ jpj:BEGIN
110               u = u[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, *]
111               v = v[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, *]
112            END
113            ELSE :BEGIN
114               zdiv = -1
115               GOTO, sortie
116            end
117
118         endcase
119;------------------------------------------------------------
120; calcul de la divergence
121;------------------------------------------------------------
122         zu = (e2u[indice2d])[*]#replicate(1, nzt)
123         zu = reform(zu, nx, ny, nzt, /over)
124         zu = temporary(u)*temporary(zu) $
125          *(umask())[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, firstzt:lastzt]
126         terreu = where(zu EQ 0)
127;;;         if terreu[0] NE -1 then zu[temporary(terreu)] = !values.f_nan
128;
129         zv = (e1v[indice2d])[*]#replicate(1, nzt)
130         zv = reform(zv, nx, ny, nzt, /over)
131         zv = temporary(v)*temporary(zv) $
132          *(vmask())[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, firstzt:lastzt]
133         terrev = where(zv EQ 0)
134;;;         if terrev[0] NE -1 then zv[temporary(terrev)] = !values.f_nan
135;
136         zdiv = 1e6/(e1t[indice2d]*e2t[indice2d])
137         zdiv = (zdiv)[*]#replicate(1, nzt)
138         zdiv = reform(zdiv, nx, ny, nzt, /over)
139         zdiv = temporary(zdiv)*(zu-shift(zu, 1, 0, 0)+zv-shift(zv, 0, 1, 0)) $
140          *tmask[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, firstzt:lastzt]
141;------------------------------------------------------------
142; mise a !values.f_nan de la bordure
143;------------------------------------------------------------
144         if NOT keyword_set(key_periodic) OR nx NE jpi then begin
145            zdiv(0, *, *) = !values.f_nan
146            zdiv(nx-1, *, *) = !values.f_nan
147         endif
148;;         zdiv(*, 0, *) = !values.f_nan
149;;         zdiv(*, ny-1, *) = !values.f_nan
150;
151         zdiv = temporary(zdiv)
152;
153         if n_elements(valmask) EQ 0 THEN valmask = 1e20
154         terre =  where(tmask[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, firstzt:lastzt] EQ 0)
155         if terre[0] NE -1 then zdiv[temporary(terre)] = valmask
156;------------------------------------------------------------
157; pour le trace graphique
158;------------------------------------------------------------
159         vargrid = 'T'
160         varname = 'div'
161         varunits = '1e6*s-1'
162         domdef, (glamt[indice2d])[0, 0], (glamu[indice2d])[nx-1, 0],(gphit[indice2d])[0, 0], (gphiv[indice2d])[0, ny-1], vert1, vert2, grille = ['t']
163         if keyword_set(direc) then zdiv = moyenne(zdiv,direc,/nan, boite = boite)
164      END
165;----------------------------------------------------------------------------
166;----------------------------------------------------------------------------
167;xyt
168;----------------------------------------------------------------------------
169;----------------------------------------------------------------------------
170      date1 NE date2 AND (size(u))[0] EQ 3 :BEGIN
171;------------------------------------------------------------
172; extraction de u et v sur le domaine qui convient
173;------------------------------------------------------------
174         case 1 of
175            (size(u))[0] NE 3 OR (size(v))[0] NE 3: return,  -1
176            (size(u))[1] EQ nxu AND (size(u))[2] EQ nyu AND $
177             (size(v))[1] EQ nxv AND (size(v))[2] EQ nyv:BEGIN
178               case 1 of
179                  nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *, *] ELSE u = u[1: nx, *, *]
180                  nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *, *] ELSE v = v[1: nx, *, *]
181                  nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1, *] ELSE u = u[*, 1: ny, *]
182                  nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1, *] ELSE v = v[*, 1: ny, *]
183                  ELSE :
184               endcase
185            END
186            (size(u))[1] EQ jpi AND (size(u))[2] EQ jpj AND $
187             (size(v))[1] EQ jpi AND (size(v))[2] EQ jpj:BEGIN
188               u = u[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, *]
189               v = v[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, *]
190            END
191            ELSE : return,  -1
192         endcase
193;------------------------------------------------------------
194; calcul de la divergence
195;------------------------------------------------------------
196         zu = e2u[indice2d]*(umask())[indice2d+jpi*jpj*firstzt]
197         terreu = where(zu EQ 0)
198;;;         if terreu[0] NE -1 then zu[temporary(terreu)] = !values.f_nan
199         zu = (zu)[*]#replicate(1, jpt)
200         zu = reform(zu, nx, ny, jpt, /over)
201         zu = temporary(u)*temporary(zu)
202;
203         zv = e1v[indice2d]*(vmask())[indice2d+jpi*jpj*firstzt]
204         terrev = where(zv EQ 0)
205;;;         if terrev[0] NE -1 then zv[temporary(terrev)] = !values.f_nan
206         zv = (zv)[*]#replicate(1, jpt)
207         zv = reform(zv, nx, ny, jpt, /over)
208         zv = temporary(v)*temporary(zv)
209;
210         zdiv = 1e6*tmask[indice2d+jpi*jpj*firstzt]/(e1t[indice2d]*e2t[indice2d])
211         zdiv = (zdiv)[*]#replicate(1, jpt)
212         zdiv = reform(zdiv, nx, ny, jpt, /over)
213         terre =  where(zdiv EQ 0)
214         zdiv = temporary(zdiv)*(zu-shift(zu, 1, 0, 0)+zv-shift(zv, 0, 1, 0))
215;------------------------------------------------------------
216; mise a !values.f_nan de la bordure
217;------------------------------------------------------------
218         if NOT keyword_set(key_periodic) OR nx NE jpi then begin
219            zdiv(0, *, *) = !values.f_nan
220            zdiv(nx-1, *, *) = !values.f_nan
221         endif
222;;         zdiv(*, 0, *) = !values.f_nan
223;;         zdiv(*, ny-1, *) = !values.f_nan
224;
225         if n_elements(valmask) EQ 0 THEN valmask = 1e20
226         if terre[0] NE -1 then zdiv[temporary(terre)] = valmask
227;------------------------------------------------------------
228; pour le trace graphique
229;------------------------------------------------------------
230         vargrid = 'T'
231         varname = 'div'
232         varunits = '1e6*s-1'
233         domdef, (glamt[indice2d])[0, 0], (glamu[indice2d])[nx-1, 0],(gphit[indice2d])[0, 0], (gphiv[indice2d])[0, ny-1], vert1, vert2, grille = ['t']
234         if keyword_set(direc) then zdiv = grossemoyenne(zdiv,direc,/nan, boite = boite)
235      END
236;----------------------------------------------------------------------------
237;----------------------------------------------------------------------------
238;xyzt
239;----------------------------------------------------------------------------
240;----------------------------------------------------------------------------
241      date1 NE date2 AND (size(u))[0] EQ 4:BEGIN
242         return, report('non code!')
243      END
244;----------------------------------------------------------------------------
245;----------------------------------------------------------------------------
246;xy
247;----------------------------------------------------------------------------
248;----------------------------------------------------------------------------
249      ELSE : BEGIN                ;xy
250         indice3d = lindgen(jpi, jpj, jpk)
251         indice3d = indice3d[indicex[0]:indicex[0]+nx-1,indicey[0]:indicey[0]+ny-1, firstzt]
252;------------------------------------------------------------
253; extraction de u et v sur le domaine qui convient
254;------------------------------------------------------------
255         case 1 of
256            (size(u))[0] NE 2 OR (size(v))[0] NE 2: BEGIN
257               zdiv = -1
258               GOTO, sortie
259            end
260            (size(u))[1] EQ nxu AND (size(u))[2] EQ nyu AND $
261             (size(v))[1] EQ nxv AND (size(v))[2] EQ nyv:BEGIN
262               case 1 of
263                  nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *] ELSE u = u[1: nx, *]
264                  nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *] ELSE v = v[1: nx, *]
265                  nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1] ELSE u = u[*, 1: ny]
266                  nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1] ELSE v = v[*, 1: ny]
267                  ELSE :
268               endcase
269            END
270            (size(u))[1] EQ jpi AND (size(u))[2] EQ jpj AND $
271             (size(v))[1] EQ jpi AND (size(v))[2] EQ jpj:BEGIN
272               u = u[indice2d]
273               v = v[indice2d]
274            END
275            ELSE : return,  -1
276         endcase
277;------------------------------------------------------------
278; calcul de la divergence
279;------------------------------------------------------------
280         zu = temporary(u)*e2u[indice2d]*(umask())[indice3d]
281         terreu = where(zu EQ 0)
282;;;         if terreu[0] NE -1 then zu[temporary(terreu)] = !values.f_nan
283         zv = temporary(v)*e1v[indice2d]*(vmask())[indice3d]
284         terrev = where(zv EQ 0)
285;;;         if terrev[0] NE -1 then zv[temporary(terrev)] = !values.f_nan
286         zdiv = zu-shift(zu, 1, 0)+zv-shift(zv, 0, 1)
287         zdiv = temporary(zdiv)*tmask[indice3d]/(e1t[indice2d]*e2t[indice2d])
288;------------------------------------------------------------
289; mise a !values.f_nan de la bordure
290;------------------------------------------------------------
291         if NOT keyword_set(key_periodic) OR nx NE jpi then begin
292            zdiv(0, *) = !values.f_nan
293            zdiv(nx-1, *) = !values.f_nan
294         endif
295;;         zdiv(*, 0) = !values.f_nan
296;;         zdiv(*, ny-1) = !values.f_nan
297;
298         zdiv = temporary(zdiv)*1e6
299;
300         if n_elements(valmask) EQ 0 THEN valmask = 1e20
301         terre =  where(tmask[indice3d] EQ 0)
302         if terre[0] NE -1 then zdiv[temporary(terre)] = valmask
303;------------------------------------------------------------
304; pour le trace graphique
305;------------------------------------------------------------
306         vargrid = 'T'
307         varname = 'div'
308         varunits = '1e6*s-1'
309         domdef, (glamt[indice2d])[0, 0], (glamu[indice2d])[nx-1, 0],(gphit[indice2d])[0, 0], (gphiv[indice2d])[0, ny-1], vert1, vert2, grille = ['t']
310         if keyword_set(direc) then zdiv = moyenne(zdiv,direc,/nan, boite = boite)
311
312      END
313   endcase
314
315;------------------------------------------------------------
316sortie:
317   if keyword_set(key_performance) THEN print, 'temps div', systime(1)-tempsun
318
319   return, zdiv
320end
Note: See TracBrowser for help on using the repository browser.