/[MITgcm]/MITgcm_contrib/gael/matlab_class/gcmfaces_calc/gcmfaces_interp_2d.m
ViewVC logotype

Contents of /MITgcm_contrib/gael/matlab_class/gcmfaces_calc/gcmfaces_interp_2d.m

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


Revision 1.8 - (show annotations) (download)
Thu Mar 3 17:04:27 2016 UTC (9 years, 4 months ago) by gforget
Branch: MAIN
CVS Tags: checkpoint65x, checkpoint65v, checkpoint65w, checkpoint65u, checkpoint66f, checkpoint66e, checkpoint66d, checkpoint66c, checkpoint66b, checkpoint66a, checkpoint66o, HEAD
Changes since 1.7: +1 -1 lines
- gcmfaces_interp_coeffs.m: add sparse matrix output (for interpolation using convert2vector.m).
- example_interp.m: add sparse matrix method exmaple (inactive).
- convert2vector.m: revised method ('new') that uses gcmfaces (old method remains the default).
- gcmfaces_interp_2d.m: remove extra ';'

1 function [val]=gcmfaces_interp_2d(fld,lon,lat,method);
2 %[val]=GCMFACES_INTERP_2D(fld,lon,lat,method);
3 % interpolates a gcmfaces field (fld) to a set of locations (lon, lat)
4 % using one of several methods: 'polygons' (default), 'natural', 'linear',
5 % 'nearest', or 'mix'.
6 %
7 % If instead fld is is an array (of the same size as lon and lat)
8 % then the field is interpolated to the gcmfaces grid (in mygrid).
9 %
10 % The 'polygons' method is a particular implementation of bilinear
11 % interpolation on the sphere. The other methods applies on DelaunayTri
12 % in longitude/latitude coordinates. In particular, the 'mix' option
13 % is `natural' extended with 'nearest' when the input field
14 % has been land-masked with NaNs.
15 %
16 %Example:
17 % lon=[-179.9:0.2:179.9]; lat=[-89.9:0.2:89.9];
18 % [lat,lon] = meshgrid(lat,lon);
19 % fld=mygrid.Depth.*mygrid.mskC(:,:,1);
20 % [val]=gcmfaces_interp_2d(fld,lon,lat);
21 % figureL; pcolor(lon,lat,val); shading flat;
22
23 % note: using gcmfaces_bindata to determine nearest neighbors on the sphere
24 % can be problematic. To illustrate the problem: uncomment the old
25 % method (using gcmfaces_bindata) in gcmfaces_loc_tile.m, set myenv.verbose
26 % to 2 and run the example as explained above. Points at the edge
27 % of tile 59 provide an example -- see display generated by
28 % gcmfaces_interp_coeffs.m
29
30 gcmfaces_global;
31
32 %backward compatibility checks:
33 if ~isfield(myenv,'useDelaunayTri');
34 myenv.useDelaunayTri=~isempty(which('DelaunayTri'));
35 end;
36
37 if isempty(whos('method')); method='polygons'; end;
38
39 if ~ischar(method);
40 error('fourth argument to gcmfaces_interp_2d is now ''method''');
41 end;
42
43 if ~myenv.useDelaunayTri&~strcmp(method,'polygons');;
44 warning('DelaunayTri is missing -> reverting to old tsearch method');
45 if ~isa(fld,'gcmfaces');
46 error('old tsearch method only treats gcmfaces inputs (fld)');
47 end;
48 end;
49
50 if ~isa(fld,'gcmfaces')&strcmp(method,'polygons');
51 error('polygons method only treats gcmfaces inputs (fld)');
52 end;
53
54 %%use TriScatteredInterp
55 if strcmp(method,'linear')|strcmp(method,'nearest')|strcmp(method,'natural')|strcmp(method,'mix');
56
57 if isa(fld,'gcmfaces');
58 XC=convert2array(mygrid.XC);
59 YC=convert2array(mygrid.YC);
60 VEC=convert2array(fld);
61 else;
62 XC=lon;
63 YC=lat;
64 VEC=fld;
65 lon=convert2gcmfaces(mygrid.XC);
66 lat=convert2gcmfaces(mygrid.YC);
67 end;
68
69 val=NaN*lon;
70 for ii=1:3;
71 if ii==1;
72 myXC=XC; myXC(myXC<0)=myXC(myXC<0)+360;
73 jj=find(lon>90);
74 elseif ii==2;
75 myXC=XC;
76 jj=find(lon>=-90&lon<=90);
77 else;
78 myXC=XC; myXC(myXC>0)=myXC(myXC>0)-360;
79 jj=find(lon<-90);
80 end;
81 kk=find(~isnan(myXC));
82 TRI=DelaunayTri(myXC(kk),YC(kk));
83 if strcmp(method,'mix');
84 F = TriScatteredInterp(TRI, VEC(kk),'natural');
85 tmp1=F(lon(jj),lat(jj));
86 F = TriScatteredInterp(TRI, VEC(kk),'nearest');
87 tmp2=F(lon(jj),lat(jj));
88 tmp1(isnan(tmp1))=tmp2(isnan(tmp1));
89 val(jj)=tmp1;
90 else;
91 F = TriScatteredInterp(TRI, VEC(kk),method);
92 val(jj)=F(lon(jj),lat(jj));
93 end;
94 end;
95
96 if ~isa(fld,'gcmfaces');
97 val=convert2gcmfaces(val);
98 end;
99
100 end;
101
102 %%old linear interpolation method:
103 if strcmp(method,'tsearch');
104
105 % Generate triangulation
106 global mytri;
107 gcmfaces_bindata;
108
109 %switch longitude range to -180+180 or 0-360 according to grid
110 if max(mygrid.XC)<0;
111 lon(find(lon>180))=lon(find(lon>180))-360;
112 end;
113 if max(mygrid.XC)>180;
114 lon(find(lon<0))=lon(find(lon<0))+360;
115 end;
116
117 % Find the nearest triangle (t)
118 x=convert2array(mygrid.XC); x=x(mytri.kk);
119 y=convert2array(mygrid.YC); y=y(mytri.kk);
120 VEC=convert2array(fld); VEC=VEC(mytri.kk);
121 t = tsearch(x,y,mytri.TRI,lon',lat')';%the order of dims matters!!
122
123 % Only keep the relevant triangles.
124 out = find(isnan(t));
125 if ~isempty(out), t(out) = ones(size(out)); end
126 tri = mytri.TRI(t(:),:);
127
128 % Compute Barycentric coordinates (w). P. 78 in Watson.
129 del = (x(tri(:,2))-x(tri(:,1))) .* (y(tri(:,3))-y(tri(:,1))) - ...
130 (x(tri(:,3))-x(tri(:,1))) .* (y(tri(:,2))-y(tri(:,1)));
131 w(:,3) = ((x(tri(:,1))-lon(:)).*(y(tri(:,2))-lat(:)) - ...
132 (x(tri(:,2))-lon(:)).*(y(tri(:,1))-lat(:))) ./ del;
133 w(:,2) = ((x(tri(:,3))-lon(:)).*(y(tri(:,1))-lat(:)) - ...
134 (x(tri(:,1))-lon(:)).*(y(tri(:,3))-lat(:))) ./ del;
135 w(:,1) = ((x(tri(:,2))-lon(:)).*(y(tri(:,3))-lat(:)) - ...
136 (x(tri(:,3))-lon(:)).*(y(tri(:,2))-lat(:))) ./ del;
137
138 val = sum(VEC(tri) .* w,2);
139 val(out)=NaN;
140 val=reshape(val,size(lon));
141
142 end;%if strcmp(method,'tsearch');
143
144
145 %%use gcmfaces_interp_coeffs (under development):
146 if strcmp(method,'polygons');
147 siz=size(lon);
148 lon=lon(:);
149 lat=lat(:);
150
151 ni=30; nj=30;
152 %ni=51; nj=51;
153 map_tile=gcmfaces_loc_tile(ni,nj);
154
155 loc_tile=gcmfaces_loc_tile(ni,nj,lon,lat);
156 loc_tile=loc_tile.tileNo;
157 [loc_interp]=gcmfaces_interp_coeffs(lon,lat,ni,nj);
158
159 fld=exch_T_N(fld);
160 [tmp1,tmp2,n3,n4]=size(fld{1});
161 arr=NaN*zeros(length(lon),n3,n4);
162
163 for ii_tile=1:max(map_tile);
164 ii=find(loc_tile==ii_tile&nansum(loc_interp.w,2));
165 if ~isempty(ii);
166 %1) determine face of current tile
167 tmp1=1*(map_tile==ii_tile);
168 tmp11=sum(sum(tmp1,1),2); tmp12=[];
169 for kk=1:tmp11.nFaces; tmp12=[tmp12,tmp11{kk}]; end;
170 ii_face=find(tmp12);
171 %... and its index range within face ...
172 tmp1=tmp1{ii_face};
173 tmp11=sum(tmp1,2);
174 iiMin=min(find(tmp11)); iiMax=max(find(tmp11));
175 tmp11=sum(tmp1,1);
176 jjMin=min(find(tmp11)); jjMax=max(find(tmp11));
177
178 %2) determine points and weights for next step
179 interp_i=1+loc_interp.i(ii,:);
180 interp_j=1+loc_interp.j(ii,:);
181 interp_k=(interp_j-1)*(ni+2)+interp_i;%index after reshape
182 interp_w=loc_interp.w(ii,:);%bininear weights
183
184 %3) get the tile array
185 til=fld{ii_face}(iiMin:iiMax+2,jjMin:jjMax+2,:,:);
186 msk=1*(~isnan(til));
187 til(isnan(til))=0;
188
189 %4) interpolate each month to profile locations
190 tmp0=repmat(interp_w,[1 1 n3 n4]);
191 tmp1=reshape(til,[(ni+2)*(nj+2) n3 n4]);
192 tmp2=reshape(msk,[(ni+2)*(nj+2) n3 n4]);
193 tmp11=tmp1(interp_k(:),:); tmp11=reshape(tmp11,[size(interp_k) n3 n4]);
194 tmp22=tmp2(interp_k(:),:); tmp22=reshape(tmp22,[size(interp_k) n3 n4]);
195 tmp1=squeeze(sum(tmp0.*tmp11,2));
196 tmp2=squeeze(sum(tmp0.*tmp22,2));
197 arr(ii,:,:,:)=tmp1./tmp2;
198
199 end;%if ~isempty(ii);
200 end;%for ii_tile=1:117;
201
202 if sum(siz~=1)<=1;
203 val=reshape(arr,[prod(siz) n3 n4]);
204 else;
205 val=reshape(arr,[siz n3 n4]);
206 end;
207 % val=squeeze(reshape(arr,[siz n3 n4]));
208 % if size(val,1)~=size(lon,1); val=val'; end;
209 end;
210

  ViewVC Help
Powered by ViewVC 1.1.22