1 |
gforget |
1.1 |
function [fld]=gcmfaces_remap_2d(lon,lat,fld,nDblRes,varargin); |
2 |
|
|
%object: use bin average to remap ONE lat-lon grid FIELD to a gcmfaces grid |
3 |
|
|
%input: lon,lat,fld are the gridded product arrays |
4 |
|
|
% nDblRes is the number of times the input field |
5 |
|
|
% resolution should be doubled before bin average. |
6 |
|
|
%optional: mskExtrap is the mask to which to extrapolate after bin average |
7 |
|
|
% If it is not specified we do no extrapolation |
8 |
|
|
%note: nDblRes>0 is useful if the starting resolution is coarse |
9 |
|
|
% enough that the bin average would leave many empty points. |
10 |
|
|
%assumption:fld should show NaN for missing values |
11 |
|
|
|
12 |
|
|
global mygrid; |
13 |
|
|
if nargin>4; mskExtrap=varargin{1}; else; mskExtrap=[]; end; |
14 |
|
|
|
15 |
|
|
%refine grid before bin average: |
16 |
|
|
for ii=1:nDblRes; |
17 |
|
|
[lon,lat,fld]=dbl_res(lon,lat,fld,ii); |
18 |
|
|
end; |
19 |
|
|
%put in vector form: |
20 |
|
|
tmp1=find(~isnan(fld)); |
21 |
|
|
lon=lon(tmp1); lat=lat(tmp1); fld=fld(tmp1); |
22 |
|
|
%switch longitude range to -180+180 |
23 |
|
|
lon(find(lon>180))=lon(find(lon>180))-360; |
24 |
|
|
%compute bin average: |
25 |
|
|
fld=gcmfaces_bindata(lon,lat,fld); |
26 |
|
|
%potential extrapolation: |
27 |
|
|
if ~isempty(mskExtrap); fld=diffsmooth2D_extrap_inv(fld,mskExtrap); end; |
28 |
|
|
%apply surface land mask: |
29 |
|
|
fld=fld.*mygrid.mskC(:,:,1); |
30 |
|
|
|
31 |
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
32 |
|
|
|
33 |
|
|
function [lonOut,latOut,obsOut]=dbl_res(lon,lat,obs,extendNaN); |
34 |
|
|
%object: use neighbor average to double the fields resolution |
35 |
|
|
%inputs: lon,lat,fld are the gridded product arrays, with |
36 |
|
|
% NaN for missing values in fld. |
37 |
|
|
% extendNaN states whether between a real and a NaN |
38 |
|
|
% we add a NaN (extendNaN==1) or a real (extendNaN~=1) |
39 |
|
|
%outputs: lonOut,latOut,fldOut are the x2 resolution arrays |
40 |
|
|
% |
41 |
|
|
%assumptions: 0-360 longitudes and a consistent ordering of arrays |
42 |
|
|
|
43 |
|
|
%check longitude range: |
44 |
|
|
if ~isempty(find(lon(:)<0))|~isempty(find(lon(:)>360)); fprintf('problem in longitude specs\n'); return; end; |
45 |
|
|
%check simple ordering: |
46 |
|
|
tmp1=diff(lon(:,1)); if ~isempty(find(tmp1<=0)); fprintf('problem in longitude specs\n'); return; end; |
47 |
|
|
|
48 |
|
|
%make sure that we are >=0 and <360: |
49 |
|
|
if lon(1,1)>0&lon(end,1)==360; lon=[lon(end,:)-360;lon(1:end-1,:)]; |
50 |
|
|
lat=[lat(end,:);lat(1:end-1,:)]; obs=[obs(end,:);obs(1:end-1,:)]; end; |
51 |
|
|
%make sure that the last point is not duplicated: |
52 |
|
|
if lon(1,1)==0&lon(end,1)==360; lon=lon(1:end-1,:); |
53 |
|
|
lat=lat(1:end-1,:); obs=obs(1:end-1,:); end; |
54 |
|
|
|
55 |
|
|
%what do we do with last longitude points: |
56 |
|
|
if lon(1,1)>0&lon(end,1)<360; |
57 |
|
|
addOnePt=1; %add point at the beginning |
58 |
|
|
else; |
59 |
|
|
addOnePt=2; %add point at the end |
60 |
|
|
end; |
61 |
|
|
|
62 |
|
|
for ii=1:3; |
63 |
|
|
%0) get field |
64 |
|
|
if ii==1; tmpA=lon; |
65 |
|
|
elseif ii==2; tmpA=lat; |
66 |
|
|
elseif ii==3; tmpA=obs; |
67 |
|
|
end; |
68 |
|
|
|
69 |
|
|
%1) zonal direction: |
70 |
|
|
tmpB=nanmean2flds(tmpA(1:end-1,:),tmpA(2:end,:),extendNaN); |
71 |
|
|
tmpC=ones(size(tmpA,1)*2-1,size(tmpA,2)); |
72 |
|
|
tmpC(1:2:end,:)=tmpA; |
73 |
|
|
tmpC(2:2:end-1,:)=tmpB; |
74 |
|
|
%treat zonal edge of the domain |
75 |
|
|
if addOnePt==1; %add one point at the beginning |
76 |
|
|
if ii==1; offset=-360; else; offset=0; end; |
77 |
|
|
tmpB=nanmean2flds(tmpA(1,:),offset+tmpA(end,:),extendNaN); tmpC=[tmpB;tmpC]; |
78 |
|
|
end; |
79 |
|
|
if addOnePt==2; %add one point at the end |
80 |
|
|
if ii==1; offset=360; else; offset=0; end; |
81 |
|
|
tmpB=nanmean2flds(offset+tmpA(1,:),tmpA(end,:),extendNaN); tmpC=[tmpC;tmpB]; |
82 |
|
|
end; |
83 |
|
|
%check that we did not go too far (should not happen) |
84 |
|
|
if ii==1; tmp1=~isempty(find(lon(:)<0))|~isempty(find(lon(:)>360)); |
85 |
|
|
if tmp1; fprintf('problem in longitude interp\n'); return; end; |
86 |
|
|
end; |
87 |
|
|
|
88 |
|
|
%2) meridional direction: |
89 |
|
|
tmpB=nanmean2flds(tmpC(:,1:end-1),tmpC(:,2:end),extendNaN); |
90 |
|
|
tmpA=ones(size(tmpC,1),size(tmpC,2)*2-1); |
91 |
|
|
tmpA(:,1:2:end)=tmpC; |
92 |
|
|
tmpA(:,2:2:end-1)=tmpB; |
93 |
|
|
|
94 |
|
|
%3) store field: |
95 |
|
|
if ii==1; lonOut=tmpA; |
96 |
|
|
elseif ii==2; latOut=tmpA; |
97 |
|
|
elseif ii==3; obsOut=tmpA; |
98 |
|
|
end; |
99 |
|
|
end; |
100 |
|
|
|
101 |
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
102 |
|
|
|
103 |
|
|
function [fld]=nanmean2flds(fld1,fld2,extendNaN); |
104 |
|
|
%object: compute the average of two fields, accounting for NaNs |
105 |
|
|
%inputs: fld1 and fld2 are the two fields |
106 |
|
|
% if extendNaN==1 the result is NaN if either fld1 or fld2 is NaN. |
107 |
|
|
% Otherwise the result is real if either fld1 or fld2 is real. |
108 |
|
|
|
109 |
|
|
if extendNaN==1; |
110 |
|
|
fld=(fld1+fld2)/2; |
111 |
|
|
else; |
112 |
|
|
msk1=~isnan(fld1); fld1(isnan(fld1))=0; |
113 |
|
|
msk2=~isnan(fld2); fld2(isnan(fld2))=0; |
114 |
|
|
fld=fld1+fld2; |
115 |
|
|
msk=msk1+msk2; |
116 |
|
|
msk(msk==0)=NaN; |
117 |
|
|
fld=fld./msk; |
118 |
|
|
end; |
119 |
|
|
|