Home > fvcom_prepro > fix_river_nodes.m

fix_river_nodes

PURPOSE ^

Takes the automatically identified river node positions generated by

SYNOPSIS ^

function Mobj = fix_river_nodes(Mobj, max_discharge, dist_thresh, varargin)

DESCRIPTION ^

 Takes the automatically identified river node positions generated by
 get_EHYPE_rivers or get_FVCOM_rivers and splits or removes them based on
 thresholds of discharge for the former and distance from the open
 boundary join with the coastline.

 Mobj = fix_river_nodes(Mobj)

 DESCRIPTION:
   The automatic identifcation of model nodes at which river inputs are
   discharged sometimes leads to problems with model stability.
   Specifically:
       1. Nodes very close to the open boundary join with the coastline
       can also cause high velocities to occur which if you have bounds
       checking enabled, will stop the model.
       2. Very large discharges into relatively small elements (e.g. the
       Rhine discharge) cause the model to crash.
       3. Rivers discharging into shallow elements can lead to
       instabilities.

   This function checks that:
       1. Rivers are deleted if their distance from the open boundary join
       with the coastline is less than the specified threshold.
       2. Any rivers with discharges above the specified threshold are
       split over a number of nodes such that each node has a maximum
       discharge less than the treshold.
       3. Optionally, each river is optimised to use the deepest node
       within ths distance threshold specified.
   This order is relatively important otherwise the splitting could put
   nodes within the land/open boundary joint radius and reduce the river
   discharge for a given river by eliminating only some of the river
   nodes.

 INPUT:
   Mobj - struct generated by get_EHYPE_rivers or get_FVCOM_rivers with
   the following fields:
       nVerts - number of nodes in the model domain
       nObs - number of open boundaries
       lon, lat - nodal positions in spherical coordinates
       tri - unstructured grid triangulation table
       read_obc_nodes - open boundary node IDs
       nRivers - number of rivers in the model domain
       river_nodes - currently identified river nodes
       river_names - currently identified river names
       river_flux - river discharge time series
   max_discharge - river discharge threshold above which rivers will be
       split over several nodes (in m^{3}s^{-1}).
   dist_thresh - distance from the open boundary nodes which connect with
       land within which nodes will be removed from the river data arrays.

   The following optional keyword-argument pairs are also supported:
   'depth_optimise' - set to a depth beyond which a search for the deepest
       node to use is triggered for the river within the distance
       threshold (dist_thresh) specified. This increases the stability of
       FVCOM. Defaults to false.
   'debug' - set to true to plot adjusted river nodes from the depth
       optimisation procedure. Defaults to false.

 OUTPUT:
   Mobj - struct with adjusted river_* fields listed above.

 TODO:
   - Check we don't split a river node into nodes which fall within the
   distance threshold for the land/open boundary joint.

 Author(s)
   Pierre Cazenave (Plymouth Marine Laboratory)

 Revision history:
   2013-12-13 First version based on the EHYPE section of my
   create_files_monthly.m script.
   2014-01-30 Fix a bug revealed when running this script on a larger
   model domain whereby the splitting of discharges across multiple
   nodes when a threshold discharge is exceeded didn't work if more than
   one river exceeded that threshold. Also add better exclusion of
   candidate river nodes (those with two land boundaries only are now
   excluded, as well as open ocean nodes and existing river nodes).
   2015-09-24 Add check for whether we actually have any rivers to
   process.
   2016-05-03 Update the number of rivers after fixing river nodes.
   2016-05-10 Add new option to pick the deepest node within the given
   radius. This is done after the splitting of river nodes but before the
   checks for a river input at a node connected to two land boundaries.
   This is because a river at a node with two land boundaries is always
   catastrophic, whereas a shallow node is sometimes catastrophic. This
   approach should also mean we minimise the risk of putting a node back
   onto a shallower node.
   2016-05-13 Move the removal of invalid coastline nodes into the
   function to read coastline nodes rather than having it in the splitting
   function.
   2016-08-11 Clarify the warning about the minimum water depth to
   indicate which way is down.
   2016-08-15 Make the depth optimisation take a depth as an argument
   rather than a boolean so we can only deepen nodes which are shallower
   than the given depth.

==========================================================================

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function Mobj = fix_river_nodes(Mobj, max_discharge, dist_thresh, varargin)
0002 % Takes the automatically identified river node positions generated by
0003 % get_EHYPE_rivers or get_FVCOM_rivers and splits or removes them based on
0004 % thresholds of discharge for the former and distance from the open
0005 % boundary join with the coastline.
0006 %
0007 % Mobj = fix_river_nodes(Mobj)
0008 %
0009 % DESCRIPTION:
0010 %   The automatic identifcation of model nodes at which river inputs are
0011 %   discharged sometimes leads to problems with model stability.
0012 %   Specifically:
0013 %       1. Nodes very close to the open boundary join with the coastline
0014 %       can also cause high velocities to occur which if you have bounds
0015 %       checking enabled, will stop the model.
0016 %       2. Very large discharges into relatively small elements (e.g. the
0017 %       Rhine discharge) cause the model to crash.
0018 %       3. Rivers discharging into shallow elements can lead to
0019 %       instabilities.
0020 %
0021 %   This function checks that:
0022 %       1. Rivers are deleted if their distance from the open boundary join
0023 %       with the coastline is less than the specified threshold.
0024 %       2. Any rivers with discharges above the specified threshold are
0025 %       split over a number of nodes such that each node has a maximum
0026 %       discharge less than the treshold.
0027 %       3. Optionally, each river is optimised to use the deepest node
0028 %       within ths distance threshold specified.
0029 %   This order is relatively important otherwise the splitting could put
0030 %   nodes within the land/open boundary joint radius and reduce the river
0031 %   discharge for a given river by eliminating only some of the river
0032 %   nodes.
0033 %
0034 % INPUT:
0035 %   Mobj - struct generated by get_EHYPE_rivers or get_FVCOM_rivers with
0036 %   the following fields:
0037 %       nVerts - number of nodes in the model domain
0038 %       nObs - number of open boundaries
0039 %       lon, lat - nodal positions in spherical coordinates
0040 %       tri - unstructured grid triangulation table
0041 %       read_obc_nodes - open boundary node IDs
0042 %       nRivers - number of rivers in the model domain
0043 %       river_nodes - currently identified river nodes
0044 %       river_names - currently identified river names
0045 %       river_flux - river discharge time series
0046 %   max_discharge - river discharge threshold above which rivers will be
0047 %       split over several nodes (in m^{3}s^{-1}).
0048 %   dist_thresh - distance from the open boundary nodes which connect with
0049 %       land within which nodes will be removed from the river data arrays.
0050 %
0051 %   The following optional keyword-argument pairs are also supported:
0052 %   'depth_optimise' - set to a depth beyond which a search for the deepest
0053 %       node to use is triggered for the river within the distance
0054 %       threshold (dist_thresh) specified. This increases the stability of
0055 %       FVCOM. Defaults to false.
0056 %   'debug' - set to true to plot adjusted river nodes from the depth
0057 %       optimisation procedure. Defaults to false.
0058 %
0059 % OUTPUT:
0060 %   Mobj - struct with adjusted river_* fields listed above.
0061 %
0062 % TODO:
0063 %   - Check we don't split a river node into nodes which fall within the
0064 %   distance threshold for the land/open boundary joint.
0065 %
0066 % Author(s)
0067 %   Pierre Cazenave (Plymouth Marine Laboratory)
0068 %
0069 % Revision history:
0070 %   2013-12-13 First version based on the EHYPE section of my
0071 %   create_files_monthly.m script.
0072 %   2014-01-30 Fix a bug revealed when running this script on a larger
0073 %   model domain whereby the splitting of discharges across multiple
0074 %   nodes when a threshold discharge is exceeded didn't work if more than
0075 %   one river exceeded that threshold. Also add better exclusion of
0076 %   candidate river nodes (those with two land boundaries only are now
0077 %   excluded, as well as open ocean nodes and existing river nodes).
0078 %   2015-09-24 Add check for whether we actually have any rivers to
0079 %   process.
0080 %   2016-05-03 Update the number of rivers after fixing river nodes.
0081 %   2016-05-10 Add new option to pick the deepest node within the given
0082 %   radius. This is done after the splitting of river nodes but before the
0083 %   checks for a river input at a node connected to two land boundaries.
0084 %   This is because a river at a node with two land boundaries is always
0085 %   catastrophic, whereas a shallow node is sometimes catastrophic. This
0086 %   approach should also mean we minimise the risk of putting a node back
0087 %   onto a shallower node.
0088 %   2016-05-13 Move the removal of invalid coastline nodes into the
0089 %   function to read coastline nodes rather than having it in the splitting
0090 %   function.
0091 %   2016-08-11 Clarify the warning about the minimum water depth to
0092 %   indicate which way is down.
0093 %   2016-08-15 Make the depth optimisation take a depth as an argument
0094 %   rather than a boolean so we can only deepen nodes which are shallower
0095 %   than the given depth.
0096 %
0097 %==========================================================================
0098 
0099 [~, subname] = fileparts(mfilename('fullpath'));
0100 
0101 global ftbverbose
0102 if ftbverbose
0103     fprintf('\nbegin : %s\n', subname)
0104 end
0105 
0106 depth_optimise = false;
0107 debug = false;
0108 for aa = 1:2:length(varargin)
0109     switch varargin{aa}
0110         case 'depth_optimise'
0111             depth_optimise = true;
0112             depth_threshold = varargin{aa + 1};
0113         case 'debug'
0114             debug = varargin{aa + 1};
0115     end
0116 end
0117 
0118 % Check we actually have some rivers to process.
0119 if Mobj.nRivers < 1
0120     warning('No rivers specified in the domain.')
0121 
0122     if ftbverbose
0123         fprintf('end   : %s\n', subname)
0124     end
0125     return
0126 end
0127 
0128 % Generate names for the variables we're going to use. These may not all be
0129 % used if you are not running ERSEM, but we build them in case.
0130 evars = {'flux', 'temp', 'salt', 'nh4', 'no3', 'o', 'p', 'sio3', 'dic', 'bioalk', 'alt'};
0131 enames = cell(length(evars));
0132 fnames = cell(length(evars));
0133 for e = 1:length(evars)
0134     enames{e} = sprintf('river_%s', evars{e});
0135     fnames{e} = sprintf('fv_%s', evars{e});
0136 end
0137 
0138 % Find the model coastline.
0139 coast_nodes = get_coastline(Mobj);
0140 
0141 % Remove river nodes close to the open boundaries.
0142 Mobj = clear_boundary_nodes(Mobj, dist_thresh, enames);
0143 
0144 % Split big rivers over adjacent nodes.
0145 Mobj = split_big_rivers(Mobj, max_discharge, coast_nodes, enames, fnames);
0146 
0147 % If we've been asked to optimise the depth of nodes, do that now. We may
0148 % have to rerun some of the checks above. I don't know yet.
0149 if depth_optimise
0150     Mobj = optimise_depth(Mobj, depth_threshold, dist_thresh, coast_nodes, debug);
0151 end
0152 
0153 % Update the number of rivers we have.
0154 Mobj.nRivers = length(Mobj.river_nodes);
0155 
0156 if ftbverbose
0157     fprintf('end   : %s\n', subname)
0158 end
0159 
0160 function coast_nodes_valid = get_coastline(Mobj)
0161 % Find the appropriate nodes from the coastline nodes. This is mostly
0162 % lifted from get_EHYPE_rivers.m.
0163 [~, ~, ~, bnd] = connectivity([Mobj.lon, Mobj.lat], Mobj.tri);
0164 boundary_nodes = 1:Mobj.nVerts;
0165 boundary_nodes = boundary_nodes(bnd);
0166 coast_nodes = boundary_nodes(~ismember(boundary_nodes, ...
0167     [Mobj.read_obc_nodes{:}]));
0168 
0169 % Remove invalid coastline nodes (from the perspective of rivers). Those
0170 % are which are connected to two land nodes. I can't think of an elegant
0171 % way of doing this, so brute force it is. This is a bit slow (~10 seconds)
0172 % on my grid with ~13000 coastal nodes.
0173 nogood = nan(size(coast_nodes)); % clear out the nans later.
0174 for nn = 1:length(coast_nodes)
0175     [row, ~] = find(Mobj.tri == coast_nodes(nn));
0176     if length(row) == 1
0177         nogood(nn) = coast_nodes(nn);
0178     end
0179 end
0180 nogood = nogood(~isnan(nogood));
0181 coast_nodes_valid = setdiff(coast_nodes, nogood);
0182 
0183 
0184 function Mobj = clear_boundary_nodes(Mobj, dist_thresh, enames)
0185 % Remove nodes close to the open boundary joint with the coastline.
0186 % Identifying the coastline/open boundary joining nodes is simply a case of
0187 % taking the first and last node ID for each open boundary. Using that
0188 % position, we can find any river nodes which fall within that distance and
0189 % simply remove their data from the relevant Mobj.river_* arrays.
0190 
0191 global ftbverbose
0192 
0193 obc_land_nodes = nan(Mobj.nObs, 2);
0194 for n = 1:Mobj.nObs
0195     obc_land_nodes(n, :) = [Mobj.read_obc_nodes{n}(1), ...
0196         Mobj.read_obc_nodes{n}(end)];
0197     for d = 1:2
0198         [dist, idx] = sort(sqrt(...
0199             (Mobj.lon(obc_land_nodes(n, d)) - Mobj.lon(Mobj.river_nodes)).^2 + ...
0200             (Mobj.lat(obc_land_nodes(n, d)) - Mobj.lat(Mobj.river_nodes)).^2 ...
0201             ));
0202         if min(dist) < dist_thresh
0203             % Delete the positions with indices less than the threshold.
0204             % This could be more than one river node.
0205             inds = find(dist < dist_thresh);
0206             if ftbverbose
0207                 % Have to loop through the indices because fprint'ing a
0208                 % cell array (the river names) is tough...
0209                 for i = 1:length(inds)
0210                     fprintf('Remove river %s at %.2f, %.2f\n', ...
0211                         Mobj.river_names{idx(inds(i))}, ...
0212                         Mobj.lon(Mobj.river_nodes(idx(inds(i)))), ...
0213                         Mobj.lat(Mobj.river_nodes(idx(inds(i)))))
0214                 end
0215             end
0216             Mobj.river_nodes(idx(inds)) = [];
0217             Mobj.river_flux(:, idx(inds)) = [];
0218             Mobj.river_names(idx(inds)) = [];
0219             % Also trim the temperature, salinity and ERSEM variables,
0220             % if we have them.
0221             for e = 1:length(enames)
0222                 if isfield(Mobj, enames{e})
0223                     Mobj.(enames{e})(:, idx(inds)) = [];
0224                 end
0225             end
0226         end
0227     end
0228 end
0229 
0230 function Mobj = split_big_rivers(Mobj, max_discharge, coast_nodes, enames, fnames)
0231 % For some of the rivers, the discharge is very large and is the source of
0232 % model instability (e.g. the Rhine crashes my irish_sea_v20 grid). So,
0233 % identify discharges in excess of some value and split that discharge over
0234 % adjacent elements, making sure they're still valid nodes and not used for
0235 % another river. Do this second so we don't have to worry about removing
0236 % nodes based on their distance from the land/open boundary joint which
0237 % have been split, which is the case if these two steps are reversed.
0238 
0239 global ftbverbose
0240 
0241 riv_idx = 1:size(Mobj.river_flux, 2);
0242 riv_idx = riv_idx(max(Mobj.river_flux) > max_discharge);
0243 
0244 if ftbverbose
0245     fprintf('%i river(s) exceed the specified discharge threshold (%.2f m^{3}s^{-1}).\n', length(riv_idx), max_discharge)
0246 end
0247 
0248 for r = riv_idx
0249     % Based on the flux data, find adjacent nodes over which to split the
0250     % data and then split all variables (both physics and, optionally,
0251     % ERSEM data).
0252 
0253     % Eliminate any existing river nodes from the list of candidates.
0254     candidates = setdiff(coast_nodes, Mobj.river_nodes);
0255 
0256     % Extract the river data for the rivers in excess of the threshold so
0257     % we can remove them from the existing arrays.
0258     for e = 1:length(enames)
0259         if isfield(Mobj, enames{e})
0260             tmp_struct.(enames{e}) = Mobj.(enames{e})(:, r);
0261         end
0262     end
0263 
0264     % Save the nodes and names of this river.
0265     river_node = Mobj.river_nodes(r);
0266     river_names = Mobj.river_names(r);
0267 
0268     % Replace the current time series with NaNs. We'll remove them after
0269     % we've split the rivers in riv_idx. If we remove them here, then the
0270     % indices in riv_idx get offset by some amount (1 position each time).
0271     % Doing that is hard to track, so we'll replace with NaNs and remove
0272     % afterwards.
0273     for e = 1:length(enames)
0274         if isfield(Mobj, enames{e})
0275             Mobj.(enames{e})(:, r) = nan;
0276         end
0277     end
0278     Mobj.river_nodes(r) = nan;
0279     Mobj.river_names{r} = 'REMOVEME';
0280 
0281     % Split the discharge based on the number of times the specified
0282     % maximum fits into the actual maximum. So, if the maximum is 10000
0283     % m^{3}s^{-1} and max_discharge is 2000 m^{3}s^{-1}, then you split
0284     % over 5 nodes.
0285     nsplit = ceil(max(tmp_struct.river_flux) / max_discharge);
0286     tmp_struct.river_flux = tmp_struct.river_flux / nsplit;
0287     % Scale the data by nsplit.
0288 %     for e = 1:length(enames)
0289 %         if isfield(Mobj, enames{e})
0290 %             tmp_struct.(enames{e}) = tmp_struct.(enames{e}) / nsplit;
0291 %         end
0292 %     end
0293 
0294     % We can keep the original node, but we need to find the
0295     % remaining nsplit-1 nodes.
0296     fv_obc = river_node;
0297     fv_names = {sprintf('%s_%i', river_names{1}, 1)};
0298     for e = 1:length(fnames)
0299         if isfield(Mobj, enames{e})
0300             tmp_struct.(fnames{e}) = repmat(tmp_struct.(enames{e}), [1, nsplit]);
0301         end
0302     end
0303 
0304     for ff = 2:nsplit
0305         % Update the list of candidates to exclude those we've just found.
0306         candidates = setdiff(candidates, fv_obc);
0307 
0308         [~, idx] = min(sqrt( ...
0309             (Mobj.lon(river_node) - Mobj.lon(candidates)).^2 + ...
0310             (Mobj.lat(river_node) - Mobj.lat(candidates)).^2));
0311 
0312         % Now we can check if this node is an FVCOM-compatible one
0313         % (element of which it's a part has no more than one land
0314         % boundary).
0315         [row, ~] = find(Mobj.tri == candidates(idx));
0316 
0317         if length(row) == 1
0318             % This is a bad node because it is a part of only one element.
0319             % The rivers need two adjacent elements to work reliably (?).
0320             % So, we need to repeat the process above until we find a node
0321             % that's connected to two elements. We'll try the other nodes
0322             % in the current element before searching the rest of the
0323             % coastline (which is computationally expensive).
0324 
0325             % Remove the current node index from the list of candidates
0326             % (i.e. leave only the two other nodes in the element).
0327             mask = Mobj.tri(row, :) ~= candidates(idx);
0328             n_tri = Mobj.tri(row, mask);
0329 
0330             % Remove values which aren't coastline values (we don't want to
0331             % set the river node to an open water node).
0332             n_tri = intersect(n_tri, candidates);
0333 
0334             % Of the remaining nodes in the element, find the closest one
0335             % to the original river location.
0336             [~, n_idx] = sort(sqrt( ...
0337                 (Mobj.rivers.positions(r, 1) - Mobj.lon(n_tri)).^2 ...
0338                 + (Mobj.rivers.positions(r, 2) - Mobj.lon(n_tri)).^2));
0339 
0340             [row_2, ~] = find(Mobj.tri == n_tri(n_idx(1)));
0341             if length(n_idx) > 1
0342                 [row_3, ~] = find(Mobj.tri == n_tri(n_idx(2)));
0343             end
0344             % Closest first
0345             if length(row_2) > 1
0346                 idx = find(candidates == n_tri(n_idx(1)));
0347                 % The other one (only if we have more than one node to
0348                 % consider).
0349             elseif length(n_idx) > 1 && length(row_3) > 1
0350                 idx = find(candidates == n_tri(n_idx(2)));
0351                 % OK, we need to search across all the other coastline
0352                 % nodes.
0353             else
0354                 % TODO: Implement a search of all the other coastline
0355                 % nodes. My testing indicates that we never get here (at
0356                 % least for the grids I've tested). I'd be interested to
0357                 % see the mesh which does get here...
0358                 continue
0359             end
0360             fprintf('alternate node ')
0361         end
0362 
0363         % Update the node ID list and the river names list. The flux we've
0364         % already done because we know it's just river_flux/nsplit in
0365         % nsplit columns.
0366         fv_obc(ff) = candidates(idx);
0367         fv_names{ff} = sprintf('%s_%i', river_names{1}, ff);
0368     end
0369 
0370     if ftbverbose
0371         fprintf('Split river %s over %i nodes.\n', river_names{1}, nsplit)
0372     end
0373 
0374     % Now we can append these new rivers to the existing list of
0375     % discharges, nodes and names.
0376     for e = 1:length(enames)
0377         if isfield(Mobj, enames{e})
0378             Mobj.(enames{e}) = [Mobj.(enames{e}), tmp_struct.(fnames{e})];
0379         end
0380     end
0381     Mobj.river_names = [Mobj.river_names; fv_names'];
0382     Mobj.river_nodes = [Mobj.river_nodes, fv_obc];
0383 end
0384 
0385 % Remove all the original river data for the split rivers. Check we're
0386 % doing the right columns by checking if the first row of the fluxes are
0387 % all NaNs for the riv_idx indices.
0388 if all(isnan(Mobj.river_flux(1, riv_idx)))
0389     for e = 1:length(enames)
0390         if isfield(Mobj, enames{e})
0391             Mobj.(enames{e})(:, riv_idx) = [];
0392         end
0393     end
0394     Mobj.river_nodes(riv_idx) = [];
0395     Mobj.river_names(riv_idx) = [];
0396 end
0397 
0398 function Mobj = optimise_depth(Mobj, depth_threshold, dist_thresh, coast_nodes, debug)
0399 % For each river node, search within the distance threshold given and pick
0400 % the deepest coastline node for that river.
0401 
0402 global ftbverbose
0403 
0404 coast_depth = Mobj.h(coast_nodes);
0405 coast_lon = Mobj.lon(coast_nodes);
0406 coast_lat = Mobj.lat(coast_nodes);
0407 
0408 for r = 1:length(Mobj.river_nodes)
0409 
0410     % The current river index in the global arrays.
0411     ri = Mobj.river_nodes(r);
0412 
0413     % Find the nearest nodes.
0414     [distance, candidates] = sort(sqrt((coast_lon - Mobj.lon(ri)).^2 + ...
0415         (coast_lat - Mobj.lat(ri)).^2));
0416     candidate_nodes = candidates(distance < dist_thresh);
0417     % Find the deepest node within the search radius.
0418     [deepest_depth, deepest_index] = max(coast_depth(candidates(distance < dist_thresh)));
0419     % Update if we've deepened this node.
0420     if ri ~= candidate_nodes(deepest_index)
0421         % Only update if we improve matters (deepen a river input node) and
0422         % are shallower than the threshold depth given.
0423         if deepest_depth > Mobj.h(ri) && Mobj.h(ri) < depth_threshold
0424             % Let everyone know what's going on.
0425             if ftbverbose
0426                 fprintf(['Moving river %s to a node with depth %.2f', ...
0427                     ' from one with a depth of %.2f (%.2fm deeper).\n'], ...
0428                     Mobj.river_names{r}, ...
0429                     Mobj.h(coast_nodes(candidate_nodes(deepest_index))), ...
0430                     Mobj.h(Mobj.river_nodes(r)), ...
0431                     Mobj.h(coast_nodes(candidate_nodes(deepest_index))) - Mobj.h(ri))
0432             end
0433 
0434             % Update the mesh object.
0435             Mobj.river_nodes(r) = coast_nodes(candidate_nodes(deepest_index));
0436 
0437             if debug
0438                 figure(1)
0439                 clf
0440                 triplot(Mobj.tri, Mobj.lon, Mobj.lat, 'k')
0441                 hold on
0442                 plot(coast_lon, coast_lat, 'r.')
0443                 scatter(coast_lon(candidates(distance < dist_thresh)), ...
0444                     coast_lat(candidates(distance < dist_thresh)), ...
0445                     30, ...
0446                     -coast_depth(candidates(distance < dist_thresh)), ...
0447                     'filled')
0448                 colorbar
0449                 plot(Mobj.lon(ri), Mobj.lat(ri), 'r^', 'MarkerSize', 20)
0450                 plot(coast_lon(candidate_nodes(deepest_index)), ...
0451                     coast_lat(candidate_nodes(deepest_index)), ...
0452                     'b^', ...
0453                     'MarkerSize', 20)
0454                 axis('tight', 'equal')
0455                 legend('grid', 'coastline', 'depths', 'original', 'new')
0456                 legend('BoxOff')
0457                 xlim([Mobj.lon(ri) - dist_thresh * 2, Mobj.lon(ri) + dist_thresh * 2])
0458                 ylim([Mobj.lat(ri) - dist_thresh * 2, Mobj.lat(ri) + dist_thresh * 2])
0459                 fprintf('Press any key to continue... \n')
0460                 pause
0461             end
0462         else
0463             continue
0464         end
0465     end
0466 end
0467 if ftbverbose
0468     fprintf('Minimum river depth is: %.2f (positive down)\n', min(Mobj.h(Mobj.river_nodes)))
0469 end

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005