0001 function [ maxCFLs, fighandle ] = show_max_CFL(grdFile, depFile, ncFile, extTS, coordtype, fig_flag)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 assert( nargin == 6, 'Wrong number of arguments.');
0023 assert( exist(grdFile, 'file')==2, 'Cannot find file %s', grdFile );
0024 assert( exist(depFile, 'file')==2, 'Cannot find file %s', depFile );
0025 assert( exist(ncFile, 'file')==2, 'Cannot find file %s', ncFile );
0026 assert( ischar(coordtype), 'Coord type must be ''lonlat'' or ''cartesian''.' );
0027 assert( islogical( fig_flag ), 'fig_flag should be logical.' );
0028
0029 switch coordtype
0030 case 'lonlat'
0031 lonlat=true;
0032 case 'latlon'
0033 lonlat=true;
0034 case 'cartesian'
0035 lonlat=false;
0036 otherwise
0037 error('Coord type must be ''lonlat'' or ''cartesian''.');
0038 end
0039
0040
0041
0042 info = ncinfo(ncFile);
0043 assert( any(strcmp('u', {info.Variables.Name})) && any(strcmp('v', {info.Variables.Name})) && ...
0044 any(strcmp('zeta', {info.Variables.Name})), 'netCDF file must include the fields u, v and zeta.' );
0045
0046
0047
0048 disp('Reading mesh & bathymetry...');
0049 M = read_fvcom_mesh( grdFile );
0050 M.h = read_fvcom_bath( depFile );
0051
0052 M.hc = mean(M.h(M.tri),2);
0053
0054 disp('Reading U velocities...');
0055 U = ncread(ncFile, 'u');
0056 disp('Reading V velocities...');
0057 V = ncread(ncFile, 'v');
0058 disp('Reading surface elevations...');
0059 Z = ncread(ncFile, 'zeta');
0060
0061 g = 9.81;
0062
0063 NumTS = size(U, 3);
0064 NumEl = size(U, 1);
0065
0066
0067
0068 disp('Calculating depths...');
0069 NodeDepths = repmat(M.h, 1, NumTS) + Z;
0070 for n = 1:3
0071 tmp(:,:,n) = NodeDepths(M.tri(:,n), :);
0072 end
0073 ElDepths = mean(tmp, 3);
0074 clear Z NodeDepths tmp;
0075
0076
0077
0078
0079
0080 disp('Calculating triangle sizes...');
0081 CharLen = nan(NumEl, 1);
0082 for e = 1:NumEl
0083 xv = M.x(M.tri(e,:));
0084 yv = M.y(M.tri(e,:));
0085
0086 xv(4) = xv(1);
0087 yv(4) = yv(1);
0088
0089 if lonlat
0090 for a = 1:3
0091 edges(a) = haversine(yv(a), xv(a), yv(a+1), xv(a+1));
0092 end
0093 else
0094 edges = sqrt( diff(xv).^2 + diff(yv).^2 );
0095 end
0096 CharLen(e) = min(edges);
0097 end
0098
0099
0100
0101
0102 maxU = squeeze(max(abs(U), [], 2));
0103 maxV = squeeze(max(abs(V), [], 2));
0104
0105
0106 CFL = ( 2 .* sqrt( g .* ElDepths ) + maxU + maxV ) .* repmat( (extTS ./ CharLen), 1, NumTS );
0107
0108
0109
0110
0111
0112 MaxCFL = max(CFL, [], 2);
0113
0114 [val, I] = max(MaxCFL);
0115 fprintf('Max CFL reached with an external timestep of %.2f secs is approx. %.3f, in Element %i.\n', extTS, val, I);
0116
0117
0118
0119 TargetCFL = 0.8;
0120 MaxTSs = repmat( (TargetCFL .* CharLen), 1, NumTS ) ./ ( 2 .* sqrt( g .* ElDepths ) + maxU + maxV );
0121
0122 OverallMaxTS = min(min(MaxTSs));
0123
0124 fprintf('Max external timestep to reach CFL of %.1f with this mesh would be approx. %.2f seconds.\n', TargetCFL, OverallMaxTS );
0125
0126
0127 if fig_flag
0128 CFLfig = figure;
0129 p = patch();
0130 p.Vertices = [M.x M.y];
0131 p.Faces = M.tri;
0132 p.CData = MaxCFL;
0133 p.FaceColor = 'flat';
0134
0135 p.EdgeColor = 'none';
0136 p.EdgeAlpha = 0.1;
0137 p.LineWidth = 0.1;
0138 cb = colorbar;
0139 colormap(parula);
0140 caxis([0 max(MaxCFL)]);
0141 ylabel(cb, 'Max CFL encountered.');
0142 axis equal;
0143
0144
0145 n = 10;
0146 [ ~, WorstEls ] = sort(MaxCFL, 'descend');
0147 WorstElsX = mean(M.x(M.tri(WorstEls(1:n),:)), 2);
0148 WorstElsY = mean(M.y(M.tri(WorstEls(1:n),:)), 2);
0149 hold on;
0150 plot(WorstElsX, WorstElsY, 'or');
0151 fprintf('Red circles on plot show the %i mesh elements with the highest CFL.\n', n);
0152 end
0153
0154
0155 maxCFLs = MaxCFL;
0156 fighandle = CFLfig;
0157
0158 end
0159
0160
0161
0162 function [distm]=haversine(lat1,lon1,lat2,lon2)
0163
0164
0165
0166
0167
0168
0169
0170
0171 lat1 = deg2rad(lat1);
0172 lat2 = deg2rad(lat2);
0173 lon1 = deg2rad(lon1);
0174 lon2 = deg2rad(lon2);
0175 R = 6371000;
0176 delta_lat = lat2 - lat1;
0177 delta_lon = lon2 - lon1;
0178 a = sin(delta_lat/2)^2 + cos(lat1) * cos(lat2) * ...
0179 sin(delta_lon/2)^2;
0180 c = 2 * atan2(sqrt(a), sqrt(1-a));
0181 distm = R * c;
0182 end