


Child function to interpolate a given 3D array (x by y by sigma) values
to the unstructured grid vertical layers.
function grid_vert_interp(Mobj, lon, lat, data, depth, mask)
DESCRIPTION:
Interpolate the regularly gridded data described by lon, lat, data
(whose size should be x by y for the lon and lat arrays, and x by y by
z for the data array) to the unstructured grid vertical layers defined
in Mobj.siglayz. The depths in depth are used to make sure the profile
is interpolated the right way up. The closest unstructured grid node
is used for the vertical interpolation of each regularly gridded node.
INPUT:
Mobj = MATLAB mesh structure which must contain:
- Mobj.have_lonlat - boolean for spherical coordinate
fields (Mobj.lon, Mobj.lat) presence (true = yes).
- Mobj.siglayz - sigma layer depths for all model
nodes.
lon, lat = Rectangular arrays of longitude and latitude (see
meshgrid).
data, depth = x by y by z (where z is vertical layers) grids of the
data and water depths to be interpolated onto the vertical grid defined
by Mobj.siglayz.
mask = logical array of positions outside the regularly gridded
domain (e.g. if the regular data contains NaNs or other undefined
values, create a logical array of those positions so they can be
omitted quickly).
'extrapolate' [optional] = keyword-argument pair in which the argument
specifies the coordinates to use for the extrapolation (e.g.
'extrapolate', [Mobj.lonc, Mobj.latc] to extrapolate onto the element
centres). Defaults to the element nodes (i.e. [Mobj.lon, Mobj.lat]).
OUTPUT:
x by y by z array of vertically interpolated values at each regular
grid location.
EXAMPLE USAGE
Basic usage:
grid_vert_interp(Mobj, lon, lat, data, depth, mask)
Extrapolate using the element centres.
grid_vert_interp(Mobj, lon, lat, data, depth, mask, ...
'extrapolate', [Mobj.lonc, Mobj.latc])
Author(s):
Pierre Cazenave (Plymouth Marine Laboratory)
Revision history
2013-02-08 First version.
2013-05-16 Add support for parallel for-loops (not mandatory, but
enabled if the Parallel Computing Toolbox is available).
2014-04-28 Add new argument to allow specifying different coordinates
for the extrapolation. This allows us to interpolate data which belongs
either to the element centres or element nodes (defaults to element
nodes). This is only really important when the model grid falls outside
the coverage of the supplied data and we're extrapolating data. Update
the parallel pool code to use the new parpool function instead of
matlabpool in anticipation of the latter's eventual removal from
MATLAB. Also update the help.
2014-06-12 Fix bug in interpolating in the vertical when HYCOM data has
only a single depth bin.
==========================================================================

0001 function dataz = grid_vert_interp(Mobj, lon, lat, data, depth, mask, varargin) 0002 % Child function to interpolate a given 3D array (x by y by sigma) values 0003 % to the unstructured grid vertical layers. 0004 % 0005 % function grid_vert_interp(Mobj, lon, lat, data, depth, mask) 0006 % 0007 % DESCRIPTION: 0008 % Interpolate the regularly gridded data described by lon, lat, data 0009 % (whose size should be x by y for the lon and lat arrays, and x by y by 0010 % z for the data array) to the unstructured grid vertical layers defined 0011 % in Mobj.siglayz. The depths in depth are used to make sure the profile 0012 % is interpolated the right way up. The closest unstructured grid node 0013 % is used for the vertical interpolation of each regularly gridded node. 0014 % 0015 % INPUT: 0016 % Mobj = MATLAB mesh structure which must contain: 0017 % - Mobj.have_lonlat - boolean for spherical coordinate 0018 % fields (Mobj.lon, Mobj.lat) presence (true = yes). 0019 % - Mobj.siglayz - sigma layer depths for all model 0020 % nodes. 0021 % lon, lat = Rectangular arrays of longitude and latitude (see 0022 % meshgrid). 0023 % data, depth = x by y by z (where z is vertical layers) grids of the 0024 % data and water depths to be interpolated onto the vertical grid defined 0025 % by Mobj.siglayz. 0026 % mask = logical array of positions outside the regularly gridded 0027 % domain (e.g. if the regular data contains NaNs or other undefined 0028 % values, create a logical array of those positions so they can be 0029 % omitted quickly). 0030 % 'extrapolate' [optional] = keyword-argument pair in which the argument 0031 % specifies the coordinates to use for the extrapolation (e.g. 0032 % 'extrapolate', [Mobj.lonc, Mobj.latc] to extrapolate onto the element 0033 % centres). Defaults to the element nodes (i.e. [Mobj.lon, Mobj.lat]). 0034 % 0035 % OUTPUT: 0036 % x by y by z array of vertically interpolated values at each regular 0037 % grid location. 0038 % 0039 % EXAMPLE USAGE 0040 % Basic usage: 0041 % grid_vert_interp(Mobj, lon, lat, data, depth, mask) 0042 % 0043 % Extrapolate using the element centres. 0044 % grid_vert_interp(Mobj, lon, lat, data, depth, mask, ... 0045 % 'extrapolate', [Mobj.lonc, Mobj.latc]) 0046 % 0047 % Author(s): 0048 % Pierre Cazenave (Plymouth Marine Laboratory) 0049 % 0050 % Revision history 0051 % 2013-02-08 First version. 0052 % 2013-05-16 Add support for parallel for-loops (not mandatory, but 0053 % enabled if the Parallel Computing Toolbox is available). 0054 % 2014-04-28 Add new argument to allow specifying different coordinates 0055 % for the extrapolation. This allows us to interpolate data which belongs 0056 % either to the element centres or element nodes (defaults to element 0057 % nodes). This is only really important when the model grid falls outside 0058 % the coverage of the supplied data and we're extrapolating data. Update 0059 % the parallel pool code to use the new parpool function instead of 0060 % matlabpool in anticipation of the latter's eventual removal from 0061 % MATLAB. Also update the help. 0062 % 2014-06-12 Fix bug in interpolating in the vertical when HYCOM data has 0063 % only a single depth bin. 0064 % 0065 %========================================================================== 0066 0067 subname = 'grid_vert_interp'; 0068 0069 global ftbverbose 0070 if ftbverbose 0071 fprintf('\n') 0072 fprintf(['begin : ' subname '\n']) 0073 end 0074 0075 if ~isfield(Mobj, 'siglayz') 0076 error('Error: missing required sigma layer depth values for the unstructured grid.') 0077 end 0078 0079 if ~Mobj.have_lonlat 0080 error('Need spherical coordinates') 0081 end 0082 0083 if sum(size(lon) ~= size(data(:, :, 1))) ~= 0 || sum(size(lat) ~= size(data(:, :, 1))) ~= 0 0084 error('Size of the longitude or latitude arrays do not match the supplied data array') 0085 end 0086 0087 % Extract the extrapolation coordinates. Default to nodes but use 0088 % whatever's given if we have the 'extrapolate' argument. 0089 ulon = Mobj.lon; 0090 ulat = Mobj.lat; 0091 for aa = 1:2:length(varargin) 0092 switch varargin{aa} 0093 case 'extrapolate' 0094 ulon = varargin{aa + 1}(:, 1); 0095 ulat = varargin{aa + 1}(:, 2); 0096 end 0097 end 0098 0099 wasOpened = false; 0100 if license('test', 'Distrib_Computing_Toolbox') 0101 % We have the Parallel Computing Toolbox, so launch a bunch of workers. 0102 try 0103 % New version for MATLAB 2014a (I think) onwards. 0104 if isempty(gcp('nocreate')) 0105 pool = parpool('local'); 0106 wasOpened = true; 0107 end 0108 catch 0109 % Version for pre-2014a MATLAB. 0110 if matlabpool('size') == 0 0111 % Force pool to be local in case we have remote pools available. 0112 matlabpool open local 0113 wasOpened = true; 0114 end 0115 end 0116 end 0117 0118 [~, fz] = size(Mobj.siglayz); 0119 [nx, ny, ~, ~] = size(data); 0120 0121 % Preallocate the output arrays 0122 dataz = nan(nx, ny, fz); 0123 0124 if ftbverbose 0125 tic 0126 end 0127 0128 parfor xi = 1:nx 0129 % Get all the y and z dimension data for the current x position 0130 % (temperature, salinity and depth). 0131 xdata = squeeze(data(xi, :, :)); 0132 xdepth = squeeze(depth(xi, :, :)); 0133 xmask = mask(xi, :); 0134 0135 % Preallocate the arrays for the inner loop. 0136 ydata = nan(ny, fz); 0137 for yi = 1:ny 0138 if xmask(yi) 0139 continue 0140 end 0141 0142 % Find the nearest sigma layer z values from the unstructured grid. 0143 [md, mi] = min(sqrt((ulon - lon(xi, yi)).^2 + (ulat - lat(xi, yi)).^2)); 0144 0145 % Skip data point if the closest FVCOM node is more than 10 minutes 0146 % away. 0147 if md > 10 / 60 0148 % if ftbverbose 0149 % fprintf('%s : skipping %f, %f (more than 10 minutes from the nearest unstructured grid node),\n', subname, lon(yi, xi), lat(yi, xi)) 0150 % end 0151 continue 0152 else 0153 % Use the FVCOM node's sigma depths to interpolate this regular 0154 % grid position's temperature and salinity data. 0155 0156 % Get the FVCOM depths closest to this regular grid position. 0157 try 0158 tfz = Mobj.siglayz(mi, :); 0159 catch 0160 tfz = Mobj.siglayzc(mi, :); 0161 end 0162 % Now get the regular grid depths at this node for all the 0163 % vertical layers and linearly interpolate through the water 0164 % column onto the FVCOM vertical profile. 0165 tpz = xdepth(yi, :); 0166 0167 % Remove any NaN values in the vertical depths (as is the case 0168 % with the HYCOM data, and interpolate only the data we have 0169 % that are finite). 0170 nidx = isnan(tpz); 0171 % If we have only a single value, repeat it down the entire 0172 % water column, otherwise, interpolate linearly (with 0173 % extrapolation). 0174 if length(tpz(~nidx)) == 1 0175 ydata(yi, :) = tpz(~nidx); 0176 else 0177 ydata(yi, :) = interp1(tpz(~nidx), xdata(yi, ~nidx), tfz, 'linear', 'extrap'); 0178 end 0179 end 0180 end 0181 dataz(xi, :, :) = ydata; 0182 end 0183 0184 % Close the MATLAB pool if we opened it. 0185 if wasOpened 0186 try 0187 pool.delete 0188 catch 0189 matlabpool close 0190 end 0191 end 0192 0193 if ftbverbose 0194 toc 0195 end 0196 0197 if ftbverbose 0198 fprintf(['end : ' subname '\n']) 0199 end