/[MITgcm]/MITgcm/pkg/exf/exf_interp.F
ViewVC logotype

Annotation of /MITgcm/pkg/exf/exf_interp.F

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.37 - (hide annotations) (download)
Fri Mar 10 00:16:11 2017 UTC (7 years, 3 months ago) by jmc
Branch: MAIN
CVS Tags: checkpoint66g, checkpoint66f, checkpoint66e, checkpoint66h
Changes since 1.36: +30 -3 lines
- interpolation with #undef EXF_INTERP_USE_DYNALLOC:
  use fixed size buffer (passed to S/R EXF_INTERP & EXF_INTERP_UV) to
  avoid any dynamic allocation

1 jmc 1.37 C $Header: /u/gcmpack/MITgcm/pkg/exf/exf_interp.F,v 1.36 2017/02/21 00:56:01 jmc Exp $
2 jmc 1.19 C $Name: $
3    
4 edhill 1.3 #include "EXF_OPTIONS.h"
5 dimitri 1.1
6 jmc 1.24 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
7 dimitri 1.1
8 jmc 1.27 CBOP
9     C !ROUTINE: EXF_INTERP
10     C !INTERFACE:
11     SUBROUTINE EXF_INTERP(
12 jmc 1.29 I inFile, filePrec,
13 jmc 1.37 #ifdef EXF_INTERP_USE_DYNALLOC
14 jmc 1.27 O arrayout,
15 jmc 1.37 #else
16     O arrayout, arrayin,
17     #endif
18 jmc 1.27 I irecord, xG_in, yG,
19 jmc 1.29 I lon_0, lon_inc, lat_0, lat_inc,
20     I nxIn, nyIn, method, myIter, myThid )
21 jmc 1.27
22     C !DESCRIPTION: \bv
23     C *==========================================================*
24     C | SUBROUTINE EXF_INTERP
25     C | o Load from file a regular lat-lon input field
26     C | and interpolate on to the model grid location
27     C *==========================================================*
28     C \ev
29    
30     C !USES:
31     IMPLICIT NONE
32     C === Global variables ===
33     #include "SIZE.h"
34     #include "EEPARAMS.h"
35     #include "PARAMS.h"
36 jmc 1.37 #include "EXF_INTERP_SIZE.h"
37 jmc 1.31 #ifdef ALLOW_DEBUG
38     # include "EXF_PARAM.h"
39     #endif
40 dimitri 1.1
41 jmc 1.27 C !INPUT/OUTPUT PARAMETERS:
42     C inFile (string) :: name of the binary input file (direct access)
43 jmc 1.20 C filePrec (integer) :: number of bits per word in file (32 or 64)
44 jmc 1.27 C arrayout ( _RL ) :: output array
45 jmc 1.37 #ifndef EXF_INTERP_USE_DYNALLOC
46     C arrayin ( _RL ) :: input field array (loaded from file)
47     #endif
48 jmc 1.20 C irecord (integer) :: record number to read
49 jmc 1.27 C xG_in,yG :: coordinates for output grid to interpolate to
50 jmc 1.20 C lon_0, lat_0 :: lon and lat of sw corner of global input grid
51     C lon_inc :: scalar x-grid increment
52     C lat_inc :: vector y-grid increments
53 jmc 1.27 C nxIn,nyIn (integer) :: size in x & y direction of input file to read
54 jmc 1.20 C method :: 1,11,21 for bilinear; 2,12,22 for bicubic
55     C :: 1,2 for tracer; 11,12 for U; 21,22 for V
56 jmc 1.29 C myIter (integer) :: current iteration number
57 jmc 1.20 C myThid (integer) :: My Thread Id number
58 jmc 1.29 CHARACTER*(*) inFile
59 jmc 1.27 INTEGER filePrec, irecord, nxIn, nyIn
60 dimitri 1.2 _RL arrayout(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
61 jmc 1.37 #ifndef EXF_INTERP_USE_DYNALLOC
62     _RL arrayin ( -1:nxIn+2, -1:nyIn+2 )
63     #endif
64 jmc 1.20 _RS xG_in (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
65 dimitri 1.2 _RS yG (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
66     _RL lon_0, lon_inc
67 jmc 1.27 c _RL lat_0, lat_inc(nyIn-1)
68 jmc 1.24 _RL lat_0, lat_inc(*)
69 jmc 1.29 INTEGER method, myIter, myThid
70 dimitri 1.1
71 jmc 1.27 C !FUNCTIONS:
72 jmc 1.29 #ifdef ALLOW_DEBUG
73 jmc 1.27 INTEGER ILNBLNK
74     EXTERNAL ILNBLNK
75 jmc 1.29 #endif
76 jmc 1.27
77     C !LOCAL VARIABLES:
78 jmc 1.29 C x_in :: longitude vector defining input field grid
79     C y_in :: latitude vector defining input field grid
80     C w_ind :: input field longitudinal index, on western side of model grid pt
81     C s_ind :: input field latitudinal index, on southern side of model grid pt
82     C bi, bj :: tile indices
83     C i, j, k, l :: loop indices
84 jmc 1.27 C msgBuf :: Informational/error message buffer
85 jmc 1.37 #ifdef EXF_INTERP_USE_DYNALLOC
86     C arrayin :: input field array (loaded from file)
87 jmc 1.27 _RL arrayin( -1:nxIn+2, -1:nyIn+2 )
88     _RL x_in(-1:nxIn+2), y_in(-1:nyIn+2)
89 jmc 1.37 #else /* EXF_INTERP_USE_DYNALLOC */
90     _RL x_in(-1:exf_max_nLon+2), y_in(-1:exf_max_nLat+2)
91     #endif /* EXF_INTERP_USE_DYNALLOC */
92 jmc 1.29 INTEGER w_ind(sNx,sNy), s_ind(sNx,sNy)
93     INTEGER bi, bj
94     INTEGER i, j, k, l
95 jmc 1.27 INTEGER nLoop
96 jmc 1.28 _RL tmpVar
97 heimbach 1.13 _RS xG(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
98 jmc 1.20 _RS threeSixtyRS
99 jmc 1.29 _RL yPole, symSign, poleValue
100 heimbach 1.13 PARAMETER ( threeSixtyRS = 360. )
101 jmc 1.29 PARAMETER ( yPole = 90. )
102     INTEGER nxd2
103 mlosch 1.33 LOGICAL xIsPeriodic, poleSymmetry
104 jmc 1.29 #ifdef ALLOW_DEBUG
105 mlosch 1.33 LOGICAL debugFlag
106 jmc 1.29 CHARACTER*(MAX_LEN_MBUF) msgBuf
107     _RS prtPole(-1:4)
108     #endif
109 jmc 1.27 CEOP
110 heimbach 1.12
111 jmc 1.37 #ifndef EXF_INTERP_USE_DYNALLOC
112     C-- Check size declaration:
113     IF ( nxIn.GT.exf_max_nLon ) THEN
114     STOP 'EXF_INTERP: exf_max_nLon too small'
115     ENDIF
116     IF ( nyIn.GT.exf_max_nLat ) THEN
117     STOP 'EXF_INTERP: exf_max_nLat too small'
118     ENDIF
119     IF ( (nxIn+4)*(nyIn+4).GT.exf_interp_bufferSize ) THEN
120     STOP 'EXF_INTERP: exf_interp_bufferSize too small'
121     ENDIF
122     #endif /* ndef EXF_INTERP_USE_DYNALLOC */
123    
124 jmc 1.29 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
125     C--- Load inut field
126 jmc 1.27
127     CALL EXF_INTERP_READ(
128     I inFile, filePrec,
129     O arrayin,
130     I irecord, nxIn, nyIn, myThid )
131 dimitri 1.2
132 jmc 1.29 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
133     C--- Prepare input grid and input field
134    
135 jmc 1.27 C-- setup input longitude grid
136     DO i=-1,nxIn+2
137 dimitri 1.18 x_in(i) = lon_0 + (i-1)*lon_inc
138 jmc 1.27 ENDDO
139     xIsPeriodic = nxIn.EQ.NINT( threeSixtyRS / lon_inc )
140 jmc 1.29 nxd2 = NINT( nxIn*0.5 )
141     poleSymmetry = xIsPeriodic .AND. ( nxIn.EQ.2*nxd2 )
142     #ifdef EXF_USE_OLD_INTERP_POLE
143     poleSymmetry = .FALSE.
144     #endif
145 heimbach 1.12
146 jmc 1.27 C-- setup input latitude grid
147 dimitri 1.18 y_in(1) = lat_0
148 jmc 1.27 DO j=1,nyIn+1
149     i = MIN(j,nyIn-1)
150     y_in(j+1) = y_in(j) + lat_inc(i)
151     ENDDO
152     y_in(0) = y_in(1) - lat_inc(1)
153     y_in(-1)= y_in(0) - lat_inc(1)
154 jmc 1.29 #ifdef ALLOW_DEBUG
155     DO l=-1,4
156     prtPole(l) = 0.
157     ENDDO
158     #endif
159     C-- For tracer (method=1,2) add 1 row @ the pole (if last row is not)
160     C and will fill it with the polarmost-row zonally averaged value.
161     C For vector component, cannot do much without the other component;
162     C averaging properly done if uvInterp=T in S/R EXF_INTERP_UV
163     #ifdef EXF_USE_OLD_INTERP_POLE
164     IF ( .TRUE. ) THEN
165     #else
166     IF ( method.LT.10 ) THEN
167     C- Add 2 row @ southern end; if one is beyond S.pole, put one @ S.pole
168     j = 0
169     IF ( ABS(y_in(j+1)).LT.yPole .AND. ABS(y_in(j)).GT.yPole ) THEN
170     y_in(j) = -yPole
171 jmc 1.35 y_in(j-1) = -2.*yPole - y_in(j+1)
172 jmc 1.29 #ifdef ALLOW_DEBUG
173     prtPole(j) = 1.
174     prtPole(j-1) = 2.
175     #endif
176     ENDIF
177     j = -1
178 jmc 1.35 IF ( ABS(y_in(j+1)).LT.yPole .AND. ABS(y_in(j)).GT.yPole ) THEN
179 jmc 1.29 y_in(j) = -yPole
180     #ifdef ALLOW_DEBUG
181     prtPole(j) = 1.
182     #endif
183     ENDIF
184     #endif /* EXF_USE_OLD_INTERP_POLE */
185 jmc 1.27 C- Add 2 row @ northern end; if one is beyond N.pole, put one @ N.pole
186 jmc 1.29 j = nyIn+1
187     IF ( ABS(y_in(j-1)).LT.yPole .AND. ABS(y_in(j)).GT.yPole ) THEN
188     y_in(j) = yPole
189     y_in(j+1) = 2.*yPole - y_in(j-1)
190     #ifdef ALLOW_DEBUG
191     prtPole(3) = 1.
192     prtPole(3+1) = 2.
193     #endif
194     ENDIF
195     j = nyIn+2
196     IF ( ABS(y_in(j-1)).LT.yPole .AND. ABS(y_in(j)).GT.yPole ) THEN
197     y_in(j) = yPole
198     #ifdef ALLOW_DEBUG
199     prtPole(4) = 1.
200     #endif
201     ENDIF
202 jmc 1.27 ENDIF
203    
204 jmc 1.29 C-- Enlarge boundary
205 jmc 1.27 IF ( xIsPeriodic ) THEN
206 jmc 1.29 C- fill-in added column assuming periodicity
207 jmc 1.27 DO j=1,nyIn
208     arrayin( 0,j) = arrayin(nxIn ,j)
209     arrayin(-1,j) = arrayin(nxIn-1,j)
210     arrayin(nxIn+1,j) = arrayin(1,j)
211     arrayin(nxIn+2,j) = arrayin(2,j)
212     ENDDO
213     ELSE
214 jmc 1.29 C- fill-in added column from nearest column
215 jmc 1.27 DO j=1,nyIn
216     arrayin( 0,j) = arrayin(1,j)
217     arrayin(-1,j) = arrayin(1,j)
218     arrayin(nxIn+1,j) = arrayin(nxIn,j)
219     arrayin(nxIn+2,j) = arrayin(nxIn,j)
220     ENDDO
221     ENDIF
222 jmc 1.29 symSign = 1. _d 0
223     IF ( method.GE.10 ) symSign = -1. _d 0
224     DO l=-1,2
225     j = l
226     IF ( l.GE.1 ) j = nyIn+l
227     k = MAX(1,MIN(j,nyIn))
228     IF ( poleSymmetry .AND. ABS(y_in(j)).GT.yPole ) THEN
229     C- fill-in added row assuming pole-symmetry
230     DO i=-1,nxd2
231     arrayin(i,j) = symSign*arrayin(i+nxd2,k)
232     ENDDO
233     DO i=1,nxd2+2
234     arrayin(i+nxd2,j) = symSign*arrayin(i,k)
235     ENDDO
236     #ifdef ALLOW_DEBUG
237     i = l + 2*( (l+1)/2 )
238     prtPole(i) = prtPole(i) + 0.2
239     #endif
240     ELSE
241     C- fill-in added row from nearest column values
242     DO i=-1,nxIn+2
243     arrayin(i,j) = arrayin(i,k)
244     ENDDO
245     ENDIF
246 jmc 1.27 ENDDO
247 dimitri 1.4
248 jmc 1.29 C-- For tracer (method=1,2) set to northernmost zonal-mean value
249 dimitri 1.15 C at 90N to avoid sharp zonal gradients near the Pole.
250 jmc 1.29 C For vector component, cannot do much without the other component;
251     C averaging properly done if uvInterp=T in S/R EXF_INTERP_UV
252     #ifdef EXF_USE_OLD_INTERP_POLE
253     IF ( .TRUE. ) THEN
254     DO l= 3,4
255     #else
256     IF ( method.LT.10 ) THEN
257     DO l=-1,4
258     #endif
259     j = l
260     IF ( l.GE.2 ) j = nyIn+l-2
261     IF ( ABS(y_in(j)).EQ.yPole ) THEN
262     IF (method.EQ.1 .OR. method.EQ.2) THEN
263     poleValue = 0.
264     DO i=1,nxIn
265     poleValue = poleValue + arrayin(i,j)
266     ENDDO
267     poleValue = poleValue / nxIn
268     DO i=-1,nxIn+2
269     arrayin(i,j) = poleValue
270     ENDDO
271     #ifdef ALLOW_DEBUG
272     prtPole(l) = prtPole(l) + 0.1
273     #endif
274     #ifdef EXF_USE_OLD_INTERP_POLE
275     ELSEIF (method.EQ.11 .OR. method.EQ.12) THEN
276     DO i=-1,nxIn+2
277     arrayin(i,j) = 0.
278     ENDDO
279     #ifdef ALLOW_DEBUG
280     prtPole(l) = prtPole(l) + 0.9
281     #endif
282     #endif /* EXF_USE_OLD_INTERP_POLE */
283     ENDIF
284 jmc 1.27 ENDIF
285 jmc 1.29 ENDDO
286     ENDIF
287    
288     #ifdef ALLOW_DEBUG
289 jmc 1.31 debugFlag = ( exf_debugLev.GE.debLevC )
290     & .OR. ( exf_debugLev.GE.debLevB .AND. myIter.LE.nIter0 )
291 jmc 1.29 C prtPole(l)=0 : extended, =1 : changed to pole, =2 : changed to symetric
292     IF ( debugFlag ) THEN
293     l = ILNBLNK(inFile)
294 jmc 1.30 _BEGIN_MASTER(myThid)
295 jmc 1.29 WRITE(msgBuf,'(3A,I6,A,2L5)')
296 jmc 1.36 & ' EXF_INTERP: file="',inFile(1:l),'", rec=', irecord,
297 jmc 1.29 & ' , x-Per,P.Sym=', xIsPeriodic, poleSymmetry
298     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
299     & SQUEEZE_RIGHT, myThid )
300 jmc 1.36 WRITE(msgBuf,'(2A,3F4.1,A,3F12.6)') ' S.edge (j=-1,0,1) :',
301 jmc 1.29 & ' proc=', (prtPole(j),j=-1,1), ', yIn=', (y_in(j),j=-1,1)
302     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
303     & SQUEEZE_RIGHT, myThid )
304 jmc 1.36 WRITE(msgBuf,'(2A,3F4.1,A,3F12.6)') ' N.edge (j=+0,+1,+2)',
305 jmc 1.29 & ' proc=', (prtPole(j),j=2,4), ', yIn=',(y_in(j),j=nyIn,nyIn+2)
306     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
307     & SQUEEZE_RIGHT, myThid )
308 jmc 1.30 _END_MASTER(myThid)
309 jmc 1.29 ENDIF
310     #endif /* ALLOW_DEBUG */
311 dimitri 1.15
312 jmc 1.29 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
313     C--- Prepare output grid and interpolate for each tile
314 dimitri 1.2
315 jmc 1.29 C-- put xG in interval [ lon_0 , lon_0+360 [
316     DO bj=myByLo(myThid),myByHi(myThid)
317     DO bi=myBxLo(myThid),myBxHi(myThid)
318     DO j=1-OLy,sNy+OLy
319     DO i=1-OLx,sNx+OLx
320     xG(i,j,bi,bj) = xG_in(i,j,bi,bj)-lon_0
321     & + threeSixtyRS*2.
322     xG(i,j,bi,bj) = lon_0+MOD(xG(i,j,bi,bj),threeSixtyRS)
323     ENDDO
324     ENDDO
325     #ifdef ALLOW_DEBUG
326 jmc 1.27 C-- Check validity of input/output coordinates
327 jmc 1.29 IF ( debugFlag ) THEN
328 jmc 1.27 DO j=1,sNy
329     DO i=1,sNx
330 mlosch 1.33 IF ( xG(i,j,bi,bj) .LT. x_in(0) .OR.
331     & xG(i,j,bi,bj) .GE. x_in(nxIn+1) .OR.
332     & yG(i,j,bi,bj) .LT. y_in(0) .OR.
333     & yG(i,j,bi,bj) .GE. y_in(nyIn+1) ) THEN
334 jmc 1.27 l = ILNBLNK(inFile)
335     WRITE(msgBuf,'(3A,I6)')
336     & 'EXF_INTERP: file="', inFile(1:l), '", rec=', irecord
337     CALL PRINT_ERROR( msgBuf, myThid )
338     WRITE(msgBuf,'(A)')
339     & 'EXF_INTERP: input grid must encompass output grid.'
340     CALL PRINT_ERROR( msgBuf, myThid )
341     WRITE(msgBuf,'(A,2I8,2I6,A,1P2E14.6)') 'i,j,bi,bj=',
342     & i,j,bi,bj, ' , xG,yG=', xG(i,j,bi,bj), yG(i,j,bi,bj)
343     CALL PRINT_ERROR( msgBuf, myThid )
344     WRITE(msgBuf,'(A,I9,A,1P2E14.6)') 'nxIn=', nxIn,
345     & ' , x_in(0,nxIn+1)=', x_in(0) ,x_in(nxIn+1)
346     CALL PRINT_ERROR( msgBuf, myThid )
347     WRITE(msgBuf,'(A,I9,A,1P2E14.6)') 'nyIn=', nyIn,
348     & ' , y_in(0,nyIn+1)=', y_in(0) ,y_in(nyIn+1)
349     CALL PRINT_ERROR( msgBuf, myThid )
350     STOP 'ABNORMAL END: S/R EXF_INTERP'
351     ENDIF
352     ENDDO
353     ENDDO
354     ENDIF
355 dimitri 1.6 #endif /* ALLOW_DEBUG */
356 jmc 1.29 ENDDO
357     ENDDO
358    
359     DO bj = myByLo(myThid), myByHi(myThid)
360     DO bi = myBxLo(myThid), myBxHi(myThid)
361 dimitri 1.1
362 mlosch 1.33 C-- Compute interpolation lon & lat index mapping
363     C-- latitude index
364     DO j=1,sNy
365     DO i=1,sNx
366     s_ind(i,j) = 0
367     w_ind(i,j) = nyIn+1
368     ENDDO
369     ENDDO
370     C # of pts = nyIn+2 ; # of interval = nyIn+1 ; evaluate nLoop as
371     C 1 + truncated log2(# interval -1); add epsil=1.e-3 for safey
372     tmpVar = nyIn + 1. _d -3
373     nLoop = 1 + INT( LOG(tmpVar)/LOG(2. _d 0) )
374     DO l=1,nLoop
375 mlosch 1.32 DO j=1,sNy
376     DO i=1,sNx
377 mlosch 1.33 IF ( w_ind(i,j).GT.s_ind(i,j)+1 ) THEN
378     k = NINT( (s_ind(i,j)+w_ind(i,j))*0.5 )
379     IF ( yG(i,j,bi,bj) .LT. y_in(k) ) THEN
380 mlosch 1.32 w_ind(i,j) = k
381 mlosch 1.33 ELSE
382 mlosch 1.32 s_ind(i,j) = k
383     ENDIF
384 mlosch 1.33 ENDIF
385 mlosch 1.32 ENDDO
386 jmc 1.27 ENDDO
387 mlosch 1.33 ENDDO
388 jmc 1.27 #ifdef ALLOW_DEBUG
389 jmc 1.29 IF ( debugFlag ) THEN
390 jmc 1.27 C- Check that we found the right lat. index
391     DO j=1,sNy
392     DO i=1,sNx
393 mlosch 1.33 IF ( w_ind(i,j).NE.s_ind(i,j)+1 ) THEN
394 jmc 1.27 l = ILNBLNK(inFile)
395     WRITE(msgBuf,'(3A,I4,A,I4)')
396     & 'EXF_INTERP: file="', inFile(1:l), '", rec=', irecord,
397     & ', nLoop=', nLoop
398     CALL PRINT_ERROR( msgBuf, myThid )
399     WRITE(msgBuf,'(A)')
400 mlosch 1.32 & 'EXF_INTERP: did not find Latitude index for grid-pt:'
401 jmc 1.27 CALL PRINT_ERROR( msgBuf, myThid )
402     WRITE(msgBuf,'(A,2I8,2I6,A,1PE16.8)')
403     & 'EXF_INTERP: i,j,bi,bj=',i,j,bi,bj,' , yG=',yG(i,j,bi,bj)
404     CALL PRINT_ERROR( msgBuf, myThid )
405     WRITE(msgBuf,'(A,I8,A,1PE16.8)')
406     & 'EXF_INTERP: s_ind=',s_ind(i,j),', lat=',y_in(s_ind(i,j))
407     CALL PRINT_ERROR( msgBuf, myThid )
408     WRITE(msgBuf,'(A,I8,A,1PE16.8)')
409     & 'EXF_INTERP: n_ind=',w_ind(i,j),', lat=',y_in(w_ind(i,j))
410     CALL PRINT_ERROR( msgBuf, myThid )
411     STOP 'ABNORMAL END: S/R EXF_INTERP'
412     ENDIF
413     ENDDO
414     ENDDO
415     ENDIF
416     #endif /* ALLOW_DEBUG */
417     C-- longitude index
418     DO j=1,sNy
419     DO i=1,sNx
420     w_ind(i,j) = INT((xG(i,j,bi,bj)-x_in(-1))/lon_inc) - 1
421     ENDDO
422     ENDDO
423 dimitri 1.1
424 jmc 1.29 C-- Do interpolation using lon & lat index mapping
425     CALL EXF_INTERPOLATE(
426     I inFile, irecord, method,
427     I nxIn, nyIn, x_in, y_in,
428 jmc 1.34 I arrayin,
429 jmc 1.29 O arrayout,
430     I xG, yG,
431     I w_ind, s_ind,
432     I bi, bj, myThid )
433 dimitri 1.1
434 jmc 1.27 ENDDO
435     ENDDO
436 dimitri 1.1
437 jmc 1.20 RETURN
438 dimitri 1.1 END

  ViewVC Help
Powered by ViewVC 1.1.22