1 |
C $Header: /u/gcmpack/models/MITgcmUV/pkg/zonal_filt/zonal_filt_presmooth.F,v 1.3 2001/02/04 14:38:51 cnh Exp $ |
2 |
C $Name: checkpoint37 $ |
3 |
|
4 |
#include "ZONAL_FILT_OPTIONS.h" |
5 |
|
6 |
SUBROUTINE ZONAL_FILT_PRESMOOTH( |
7 |
I holeMask, |
8 |
U field, |
9 |
O avgField, |
10 |
I lField, |
11 |
I myThid ) |
12 |
C /==========================================================\ |
13 |
C | S/R ZONAL_FILT_PRESMOOTH | |
14 |
C | o Smooth data with holes ready for FFT. | |
15 |
C |==========================================================| |
16 |
C | FFT routines act on a series of data points. Having | |
17 |
C | arbitrary values in land introduces unrealistic noise in | |
18 |
C | the series. A better approach is to linearly ramp data | |
19 |
C | through the missing points. The mean of the field is also| |
20 |
C | removed. The mean is restored in FFT_POSTSMOOTH. This | |
21 |
C | step ensures no bias is introduced by the FFT process - | |
22 |
C | strictly it isnt necessary, but it can help improve | |
23 |
C | numerical conditioning. | |
24 |
C \==========================================================/ |
25 |
IMPLICIT NONE |
26 |
|
27 |
C == Global data == |
28 |
#include "SIZE.h" |
29 |
#include "EEPARAMS.h" |
30 |
#include "PARAMS.h" |
31 |
#include "GRID.h" |
32 |
|
33 |
C == Routine arguments == |
34 |
C holeMask - Array with 0 for holes and != 0 for valid data. |
35 |
C lField - Length of field to smooth (assumed periodic) |
36 |
C field - Field smoothed. |
37 |
C myThid - Thread number of this instance of FFT_PRESMOOTH_IN_X |
38 |
INTEGER lField |
39 |
Real*8 holeMask(lField) |
40 |
Real*8 field(lField) |
41 |
Real*8 avgField |
42 |
INTEGER myThid |
43 |
|
44 |
#ifdef ALLOW_ZONAL_FILT |
45 |
|
46 |
C == Local variables ==== |
47 |
C I - Loop counter |
48 |
C lbuf - Size of buffer arrays |
49 |
C hBase - Coord for last valid data point. |
50 |
C hHead - Coord for next valid data point. |
51 |
C hLo - Index for last valid data point. |
52 |
C hHi - Index for next valid data point. |
53 |
C nValid - Count of valid data points. |
54 |
C dist, len - Temps for interpolating. |
55 |
C frac Interpolation is simple linear ramp |
56 |
C between end-point in grid-point space. |
57 |
C e.g. for a series of points |
58 |
C Index 1 2 3 4 5 6 7 8 9 10 11 12 |
59 |
C Data M V M M M M V V V V V V |
60 |
C where M indicates missing data and V valid |
61 |
C and 1 2 3 .... are indexes in field. Values |
62 |
C for the M points are found by interpolating |
63 |
C between the two V values that bracket a series |
64 |
C of M point. For index=1 |
65 |
C dist=1, len=2 and frac=dist/len=1/2 so that |
66 |
C the interpolated value at index=1 is |
67 |
C V(index=12)+frac*( V(index=2)-V(index=12) ). |
68 |
C For index=5 dist=3, len=5 and frac=dist/len=3/5 |
69 |
C so interpolated value at index=5 is |
70 |
C V(index=2)+frac*( V(index=7)-V(index=2) ). |
71 |
C lastGood - Temp for tracking of last good data point index. |
72 |
C nValid - Temp for counting number of valid points. |
73 |
C |
74 |
INTEGER lBuf |
75 |
PARAMETER ( lBuf = sNx ) |
76 |
INTEGER hBase(lBuf) |
77 |
INTEGER hHead(lBuf) |
78 |
INTEGER hLo(lBuf) |
79 |
INTEGER hHi(lBuf) |
80 |
INTEGER lastGood |
81 |
_RL dist |
82 |
_RL len |
83 |
_RL frac |
84 |
INTEGER nValid |
85 |
INTEGER I, iLo, iHi |
86 |
|
87 |
|
88 |
C |
89 |
IF ( lField .GT. lBuf ) THEN |
90 |
STOP 'S/R FFT_PRESMOOTH_1D: lField .GT. lBuf' |
91 |
ENDIF |
92 |
|
93 |
CcnhDebugStarts |
94 |
C WRITE(*,*) 'Before FFT pre-smooth' |
95 |
C WRITE(*,'(A,A)') 'Mask ', 'Data' |
96 |
C DO I=1,lField |
97 |
C WRITE(*,'(A,I4,1X,F3.1,1X,1PE35.25)') 'I= ',I,holeMask(I), field(I) |
98 |
C ENDDO |
99 |
CcnhDebugEnds |
100 |
|
101 |
C Count number of valid data points |
102 |
nValid = 0 |
103 |
avgField = 0. |
104 |
DO I=1,lField |
105 |
IF ( holeMask(I) .NE. 0. ) THEN |
106 |
nValid = nValid+1 |
107 |
avgField = avgField+field(I) |
108 |
ENDIF |
109 |
ENDDO |
110 |
|
111 |
IF ( lField .GT. 1 .AND. nValid .GT. 0 ) THEN |
112 |
C Get lists of hole starts, ends and extents |
113 |
C ( use periodic wrap around ). |
114 |
|
115 |
C 1. hLo - Index of valid point at start of run of holes |
116 |
C hBase - Coord of hLo (used to get offset when interpolating). |
117 |
C Note: The mean is also subtracted from field here. |
118 |
lastGood = -1 |
119 |
avgField = avgField/FLOAT(nValid) |
120 |
DO I=1,lField |
121 |
IF ( holeMask(I) .EQ. 0. ) THEN |
122 |
C A hole |
123 |
hLo (I) = lastGood |
124 |
hBase(I) = lastGood |
125 |
ELSE |
126 |
C Data |
127 |
hLo(I) = 0 |
128 |
hBase(I) = 0 |
129 |
lastGood = I |
130 |
field(I) = field(I)-avgField |
131 |
ENDIF |
132 |
ENDDO |
133 |
DO I=1,lField |
134 |
IF ( hLo(I) .EQ. -1 ) THEN |
135 |
hLo(I) = lastGood |
136 |
hBase(I) = lastGood-lField |
137 |
ENDIF |
138 |
ENDDO |
139 |
|
140 |
C 2. hHi - Coord of valid point at end of run of holes. |
141 |
lastGood = -1 |
142 |
DO I=lField,1,-1 |
143 |
IF ( holeMask(I) .EQ. 0. ) THEN |
144 |
C A hole |
145 |
hHi(I) = lastGood |
146 |
hHead(I) = lastGood |
147 |
ELSE |
148 |
C Data |
149 |
hHi(I) = 0 |
150 |
lastGood = I |
151 |
ENDIF |
152 |
ENDDO |
153 |
DO I=lField,1,-1 |
154 |
IF ( hHi(I) .EQ. -1 ) THEN |
155 |
hHi(I) = lastGood |
156 |
hHead(I) = lastGood+lField |
157 |
ENDIF |
158 |
ENDDO |
159 |
|
160 |
CcnhDebugStarts |
161 |
C WRITE(*,*) 'During FFT pre-smooth' |
162 |
C WRITE(*,'(A,A,A,A,A,A)') 'I ','mask(I)','hHi(I)','hLo(I)','hBase(I)','hHead(I)' |
163 |
C DO I=1,lField |
164 |
C WRITE(*,'(6(I4,1X))') |
165 |
C & I,INT(holeMask(I)),hHi(I),hLo(I),hBase(I),hHead(I) |
166 |
C ENDDO |
167 |
CcnhDebugEnds |
168 |
|
169 |
C 3. Interpolate |
170 |
DO I=1,lField |
171 |
IF ( holeMask(I) .EQ. 0. ) THEN |
172 |
C A hole |
173 |
iLo = hLo(I) |
174 |
iHi = hHi(I) |
175 |
dist = I-hBase(I) |
176 |
len = hHead(I) - hBase(I) |
177 |
CcnhDebugStarts |
178 |
C WRITE(*,'(A,1X,I4,1X,1PE35.25,1X,1PE35.25,)') 'I= ',I,dist, len |
179 |
C IF ( dist .LT. 0 ) STOP ' DIST .LT. 0 ' |
180 |
C IF ( len .LT. 0 ) STOP ' LEN .LT. 0 ' |
181 |
C IF ( dist .GT. lField ) STOP ' dist .GT. lField ' |
182 |
C IF ( len .GT. lField ) STOP ' len .GT. lField ' |
183 |
C IF ( dist .GT. len ) STOP ' dist .GT. len ' |
184 |
CcnhDebugStarts |
185 |
frac = dist/len |
186 |
field(I) = field(iLo) |
187 |
& +(field(iHi)-field(iLo))*frac |
188 |
ENDIF |
189 |
ENDDO |
190 |
|
191 |
CcnhDebugStarts |
192 |
C WRITE(*,*) 'After FFT pre-smooth' |
193 |
C WRITE(*,'(A,A)') 'Mask ', 'Data' |
194 |
C DO I=1,lField |
195 |
C WRITE(*,'(A,I4,1X,F3.1,1X,1PE35.25)') 'I= ',I,holeMask(I), field(I) |
196 |
C ENDDO |
197 |
CcnhDebugEnds |
198 |
|
199 |
ENDIF |
200 |
C |
201 |
#endif /* ALLOW_ZONAL_FILT */ |
202 |
|
203 |
RETURN |
204 |
END |