


Read an FVCOM sigma layers file and output z values into Mobj.
Mobj = read_sigma(Mobj, sigmafile)
DESCRIPTION:
Read a sigma file and calculate the sigma layer depths
INPUT:
Mobj: Mesh object which must contain Mobj.h (depths).
sigmafile : Full path to an FVCOM sigma.dat file.
OUTPUT:
Mobj: Mesh object with four new fields:
- siglayz and siglevz: contain depths of the sigma layers
and levels at each grid node.
- siglayzc and siglevzc: contain depths of the sigma layers
and levels at each element centre.
- siglay and siglev: the sigma layer and levels in the
range 0 to -1.
EXAMPLE USAGE:
Mobj = read_sigma(Mobj, 'sigma.dat')
Author(s):
Pierre Cazenave (Plymouth Marine Laboratory)
Revision history
2013-01-08 Based on the code in show_sigma.m but instead of calculating
sigma layers along a user-defined line, the depths are calculated for
each node in the unstructured grid.
2013-01-10 Added two new outputs to the returned Mobj (siglay and
siglev). They're useful in write_FVCOM_tsobc.m.
2013-04-23 Add support for geometric sigma distributions as well as
slightly more robust reading of and checks on the parameters in the
input file. Also changed the way the uniform distribution is calculated
(by using a P_SIGMA value of 1 and the sigma_geo.m function rather than
fiddling around with ranges, although the output is the same).
2014-04-28 Add the sigma levels for the element centres in addition to
the element nodes.
2016-05-25 Made the sigma distributions be spatially resolved for the
UNIFORM, GEOMETRIC and GENERALIZED cases. Also removed the UNIFORM
distribution from the checks on the values of parameters which only
belong in the GENERALIZED case.

0001 function Mobj = read_sigma(Mobj, sigmafile) 0002 % Read an FVCOM sigma layers file and output z values into Mobj. 0003 % 0004 % Mobj = read_sigma(Mobj, sigmafile) 0005 % 0006 % DESCRIPTION: 0007 % Read a sigma file and calculate the sigma layer depths 0008 % 0009 % INPUT: 0010 % Mobj: Mesh object which must contain Mobj.h (depths). 0011 % sigmafile : Full path to an FVCOM sigma.dat file. 0012 % 0013 % OUTPUT: 0014 % Mobj: Mesh object with four new fields: 0015 % - siglayz and siglevz: contain depths of the sigma layers 0016 % and levels at each grid node. 0017 % - siglayzc and siglevzc: contain depths of the sigma layers 0018 % and levels at each element centre. 0019 % - siglay and siglev: the sigma layer and levels in the 0020 % range 0 to -1. 0021 % 0022 % EXAMPLE USAGE: 0023 % Mobj = read_sigma(Mobj, 'sigma.dat') 0024 % 0025 % Author(s): 0026 % Pierre Cazenave (Plymouth Marine Laboratory) 0027 % 0028 % Revision history 0029 % 2013-01-08 Based on the code in show_sigma.m but instead of calculating 0030 % sigma layers along a user-defined line, the depths are calculated for 0031 % each node in the unstructured grid. 0032 % 2013-01-10 Added two new outputs to the returned Mobj (siglay and 0033 % siglev). They're useful in write_FVCOM_tsobc.m. 0034 % 2013-04-23 Add support for geometric sigma distributions as well as 0035 % slightly more robust reading of and checks on the parameters in the 0036 % input file. Also changed the way the uniform distribution is calculated 0037 % (by using a P_SIGMA value of 1 and the sigma_geo.m function rather than 0038 % fiddling around with ranges, although the output is the same). 0039 % 2014-04-28 Add the sigma levels for the element centres in addition to 0040 % the element nodes. 0041 % 2016-05-25 Made the sigma distributions be spatially resolved for the 0042 % UNIFORM, GEOMETRIC and GENERALIZED cases. Also removed the UNIFORM 0043 % distribution from the checks on the values of parameters which only 0044 % belong in the GENERALIZED case. 0045 0046 [~, subname] = fileparts(mfilename('fullpath')); 0047 0048 global ftbverbose 0049 if ftbverbose 0050 fprintf('\nbegin : %s\n', subname) 0051 end 0052 0053 fid = fopen(sigmafile,'r'); 0054 assert(fid >= 0, 'Sigma file: %s does not exist', sigmafile) 0055 0056 while ~feof(fid) 0057 line = fgetl(fid); 0058 if isempty(line) || strncmp(line, '!', 1) || ~ischar(line) 0059 continue 0060 end 0061 0062 % Clean up the input string to make matching a bit easier (trim 0063 % whitespace and remove duplicate spaces in the keywords). 0064 C = strtrim(regexpi(regexprep(line, '\s+', ' '), '=', 'split')); 0065 0066 switch lower(C{1}) 0067 case 'number of sigma levels' 0068 nlev = str2double(C{2}); 0069 case 'sigma coordinate type' 0070 sigtype = C{2}; 0071 case 'sigma power' 0072 sigpow = str2double(C{2}); 0073 case 'du' 0074 du = str2double(C{2}); 0075 case 'dl' 0076 dl = str2double(C{2}); 0077 case 'min constant depth' 0078 min_constant_depth = str2double(C{2}); 0079 case 'ku' 0080 ku = str2double(C{2}); 0081 case 'kl' 0082 kl = str2double(C{2}); 0083 case 'zku' 0084 s = str2double(regexp(C{2}, ' ', 'split')); 0085 zku = zeros(ku, 1); 0086 for i = 1:ku 0087 zku(i) = s(i); 0088 end 0089 case 'zkl' 0090 s = str2double(regexp(C{2}, ' ', 'split')); 0091 zkl = zeros(kl, 1); 0092 for i = 1:kl 0093 zkl(i) = s(i); 0094 end 0095 end 0096 end 0097 0098 % Do some checks if we've got uniform or generalised coordinates to make 0099 % sure the input is correct. 0100 if strcmpi(sigtype, 'GENERALIZED') 0101 if numel(zku) ~= ku 0102 warning('Number of zku values does not match the number specified in ku') 0103 end 0104 if numel(zkl) ~= kl 0105 warning('Number of zkl values does not match the number specified in kl') 0106 end 0107 end 0108 0109 if ftbverbose 0110 % Should be present in all sigma files. 0111 fprintf('nlev\t%d\n', nlev) 0112 fprintf('sigtype\t%s\n', sigtype) 0113 Mobj.nlev = nlev; 0114 Mobj.sigtype = sigtype; 0115 % Only present in geometric sigma files. 0116 if strcmpi(sigtype, 'GEOMETRIC') 0117 fprintf('sigpow\t%d\n', sigpow) 0118 Mobj.sigpow = sigpow; 0119 end 0120 0121 % Only in the generalised or uniform sigma files. 0122 if strcmpi(sigtype, 'GENERALIZED') 0123 fprintf('du\t%d\n', du) 0124 fprintf('dl\t%d\n', dl) 0125 fprintf('min_constant_depth\t%f\n', min_constant_depth) 0126 fprintf('ku\t%d\n', ku) 0127 fprintf('kl\t%d\n', kl) 0128 fprintf('zku\t%d\n', zku) 0129 fprintf('zkl\t%d\n', zkl) 0130 Mobj.du = du; 0131 Mobj.dl = dl; 0132 Mobj.min_constant_depth = min_constant_depth; 0133 Mobj.ku = ku; 0134 Mobj.kl = kl; 0135 Mobj.zku = zku; 0136 Mobj.zkl = zkl; 0137 end 0138 if strcmpi(sigtype, 'TANH') 0139 fprintf('du\t%d\n', du) 0140 fprintf('dl\t%d\n', dl) 0141 Mobj.du = du; 0142 Mobj.dl = dl; 0143 end 0144 end 0145 0146 % Calculate the sigma distributions at each grid node. 0147 nx = length(Mobj.h); 0148 switch lower(sigtype) 0149 case 'generalized' 0150 z = nan([nx, nlev]); 0151 h = Mobj.h; % avoids broadcasting Mobj on every iteration 0152 % Not sure if a parfor is wise here as the pool start up time might 0153 % exceed the run time. For big grids, the parfor is probably a wise 0154 % move. 0155 parfor i = 1:nx 0156 z(i, :) = sigma_gen(nlev, dl, du, kl, ku, zkl, zku, ... 0157 h(i), min_constant_depth); 0158 end 0159 clear h 0160 case 'uniform' 0161 z = repmat(sigma_geo(nlev, 1), [nx, 1]); 0162 case 'geometric' 0163 z = repmat(sigma_geo(nlev, sigpow), [nx, 1]); 0164 case 'tanh' 0165 z = repmat(sigma_tanh(nlev, dl,du), [nx, 1]); 0166 otherwise 0167 error('Don''t recognise sigtype %s (is it supported?)', sigtype) 0168 end 0169 0170 % Create a depth array for the element centres. 0171 hc = nodes2elems(Mobj.h, Mobj); 0172 ne = length(hc); 0173 0174 % Create a siglay variable (i.e. midpoint in the sigma levels). 0175 zlay = z(:, 1:end - 1) + (diff(z, [], 2) ./ 2); 0176 zlayc = nan(ne, nlev - 1); 0177 zc = nan(ne, nlev); 0178 for i = 1:nlev 0179 zc(:, i) = nodes2elems(z(:, i), Mobj); 0180 if i ~= nlev 0181 zlayc(:, i) = nodes2elems(zlay(:, i), Mobj); 0182 end 0183 end 0184 Mobj.siglevz = repmat(Mobj.h, 1, nlev) .* z; 0185 Mobj.siglayz = repmat(Mobj.h, 1, nlev-1) .* zlay; 0186 Mobj.siglevzc = repmat(hc, 1, nlev) .* zc; 0187 Mobj.siglayzc = repmat(hc, 1, nlev-1) .* zlayc; 0188 Mobj.siglayc = zlayc; 0189 Mobj.siglevc = zc; 0190 % Add the sigma levels and layers to the Mobj. 0191 Mobj.siglev = z; 0192 Mobj.siglay = zlay; 0193 0194 if ftbverbose 0195 fprintf('end : %s\n', subname) 0196 end