Home > fvcom_prepro > write_FVCOM_tsobc.m

write_FVCOM_tsobc

PURPOSE ^

Export temperature and salinity forcing at the open boundary.

SYNOPSIS ^

function write_FVCOM_tsobc(basename,time,nSiglay,in_temp,in_salt,Mobj,varargin)

DESCRIPTION ^

 Export temperature and salinity forcing at the open boundary.

 function write_FVCOM_tsobc(basename,time,nSiglay,in_temp,in_salt)

 DESCRIPTION:
    Setup an FVCOM hydrographic open boundary forcing file. Supply either
    uniform values for temperature and salinity or 3D arrays (node,
    sigma_layers, time).

 INPUT
    basename - Model case name (to find the bathymetry and open boundary
    .dat files).
    time - Time (Modified Julian Days)
    nSiglay - Number of sigma layers
    in_temp - Boundary temperature (Celsius)
    in_salt - Boundary salinity (psu)
    Mobj - Mesh Object with the following fields:
       - nObs - number of open boundaries
       - read_obc_nodes - open boundary node cell array (length = nObs)
       - siglay - sigma layer definitions
       - siglev - sigma level definitions
    Optional keyword-argument pairs:

    'strtime' = set to true to output the 'Times' variable
    'inttime' = set to true to output the 'Itime' and 'Itime2' variables
    'floattime' = set to true to output the 'time' variable

    This script defaults to writing 'Times' only.

    FVCOM needs only one of:
        1. Times: character string of times
        2. Itime and Itime2: integer days and milliseconds since midnight
        3. time: float days.
    FVCOM checks for these in the order above and this script defaults to
    writing Times only. Adjust the keyword-argument pairs to your liking.

 OUTPUT:
    FVCOM hydrographic open boundary netCDF file

 Author(s):
    Geoff Cowles (University of Massachusetts Dartmouth)
    Pierre Cazenave (Plymouth Marine Laboratory)
    Karen Amoudry (National Oceanography Centre, Liverpool)

 PWC Revision history
    2012-06-15 Added support for native MATLAB NetCDF routines. Requires
    MATLAB 2010a or higher.
    2012-07-16 Removed hard-coded nSiglay and nSiglev and instead moved to
    arguments list.
    2012-10-08 Updated help to reflect the fact nSiglev is calculated as
    nSiglay+1.
    2012-11-09 Add new arguments to use user defined temperature and
    salinity.
    2013-01-09 Add support for 3D input temperature and salinity (such as
    might be generated with get_POLCOMS_tsobc.m.
    2016-05-25 Removed the reads of the ASCII configuration files (which
    was very slow) and instead extracted the relevant information from the
    supplied mesh object. As such, the requirements for the mesh object
    have changed, so hopefully this won't bite too many people in the
    behind. Also simplified the allocation of the arrays when uniform
    values are given (i.e. when in_salt and in_temp are scalars).

 KJA Revision history
    Undated - Add better check for the size of the input arrays (works
    with scalars).
    2013-08-16 - Updated output of Itime2 to avoid rounding errors
    when converting from double to single format.

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

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function write_FVCOM_tsobc(basename,time,nSiglay,in_temp,in_salt,Mobj,varargin)
0002 % Export temperature and salinity forcing at the open boundary.
0003 %
0004 % function write_FVCOM_tsobc(basename,time,nSiglay,in_temp,in_salt)
0005 %
0006 % DESCRIPTION:
0007 %    Setup an FVCOM hydrographic open boundary forcing file. Supply either
0008 %    uniform values for temperature and salinity or 3D arrays (node,
0009 %    sigma_layers, time).
0010 %
0011 % INPUT
0012 %    basename - Model case name (to find the bathymetry and open boundary
0013 %    .dat files).
0014 %    time - Time (Modified Julian Days)
0015 %    nSiglay - Number of sigma layers
0016 %    in_temp - Boundary temperature (Celsius)
0017 %    in_salt - Boundary salinity (psu)
0018 %    Mobj - Mesh Object with the following fields:
0019 %       - nObs - number of open boundaries
0020 %       - read_obc_nodes - open boundary node cell array (length = nObs)
0021 %       - siglay - sigma layer definitions
0022 %       - siglev - sigma level definitions
0023 %    Optional keyword-argument pairs:
0024 %
0025 %    'strtime' = set to true to output the 'Times' variable
0026 %    'inttime' = set to true to output the 'Itime' and 'Itime2' variables
0027 %    'floattime' = set to true to output the 'time' variable
0028 %
0029 %    This script defaults to writing 'Times' only.
0030 %
0031 %    FVCOM needs only one of:
0032 %        1. Times: character string of times
0033 %        2. Itime and Itime2: integer days and milliseconds since midnight
0034 %        3. time: float days.
0035 %    FVCOM checks for these in the order above and this script defaults to
0036 %    writing Times only. Adjust the keyword-argument pairs to your liking.
0037 %
0038 % OUTPUT:
0039 %    FVCOM hydrographic open boundary netCDF file
0040 %
0041 % Author(s):
0042 %    Geoff Cowles (University of Massachusetts Dartmouth)
0043 %    Pierre Cazenave (Plymouth Marine Laboratory)
0044 %    Karen Amoudry (National Oceanography Centre, Liverpool)
0045 %
0046 % PWC Revision history
0047 %    2012-06-15 Added support for native MATLAB NetCDF routines. Requires
0048 %    MATLAB 2010a or higher.
0049 %    2012-07-16 Removed hard-coded nSiglay and nSiglev and instead moved to
0050 %    arguments list.
0051 %    2012-10-08 Updated help to reflect the fact nSiglev is calculated as
0052 %    nSiglay+1.
0053 %    2012-11-09 Add new arguments to use user defined temperature and
0054 %    salinity.
0055 %    2013-01-09 Add support for 3D input temperature and salinity (such as
0056 %    might be generated with get_POLCOMS_tsobc.m.
0057 %    2016-05-25 Removed the reads of the ASCII configuration files (which
0058 %    was very slow) and instead extracted the relevant information from the
0059 %    supplied mesh object. As such, the requirements for the mesh object
0060 %    have changed, so hopefully this won't bite too many people in the
0061 %    behind. Also simplified the allocation of the arrays when uniform
0062 %    values are given (i.e. when in_salt and in_temp are scalars).
0063 %
0064 % KJA Revision history
0065 %    Undated - Add better check for the size of the input arrays (works
0066 %    with scalars).
0067 %    2013-08-16 - Updated output of Itime2 to avoid rounding errors
0068 %    when converting from double to single format.
0069 %
0070 %==========================================================================
0071 
0072 if nargin == 5
0073     warning(['Assuming uniform terrain-following sigma coordinates. ', ...
0074         'To specify different sigma coordintes, supply a MATLAB mesh ', ...
0075         'structure with fields siglay and siglev.'])
0076 end
0077 
0078 [~, subname] = fileparts(mfilename('fullpath'));
0079 global ftbverbose
0080 if ftbverbose
0081   fprintf('\nbegin : %s\n', subname)
0082 end
0083 
0084 % Default to string times as FVCOM looks for these first.
0085 strtime = true;
0086 inttime = false;
0087 floattime = false;
0088 for vv = 1:2:length(varargin)
0089     switch varargin{vv}
0090         case 'strtime'
0091             strtime = true;
0092         case 'inttime'
0093             inttime = true;
0094         case 'floattime'
0095             floattime = true;
0096     end
0097 end
0098 
0099 tsOBCFile = [basename, '_tsobc.nc'];
0100 
0101 obc_nodes = [Mobj.read_obc_nodes{:}]';
0102 obc_h = Mobj.h(obc_nodes);
0103 siglev = Mobj.siglev(obc_nodes, :);
0104 siglay = Mobj.siglay(obc_nodes, :);
0105 
0106 nTimes = length(time);
0107 nObc = length(obc_nodes);
0108 nSiglev = nSiglay + 1;
0109 
0110 %--------------------------------------------------------------------------
0111 % Generate the requisite data
0112 %--------------------------------------------------------------------------
0113 
0114 if isscalar(in_temp) && isscalar(in_salt)
0115     % Make 3D arrays from the scalar values given.
0116     temp = repmat(in_temp, [nObc, nSiglay, nTimes]);
0117     salt = repmat(in_salt, [nObc, nSiglay, nTimes]);
0118 else
0119     % We have a 3D array already.
0120     temp = in_temp;
0121     salt = in_salt;
0122 end
0123 clear in_temp in_salt
0124 
0125 % We need to make sigma level and layer data resolved for each node on the
0126 % open boundary (in case we have hybrid coordinates).
0127 if isvector(siglev)
0128     siglev = repmat(siglev, [nObc, 1]);
0129 end
0130 if isvector(siglay)
0131     siglay = repmat(siglay, [nObc, 1]);
0132 end
0133 
0134 % Check we've got everything the right size and shape.
0135 if nSiglev ~= size(temp, 2) + 1 || size(siglev, 2) ~= size(temp, 2) + 1 || size(siglev, 2) ~= size(salt, 2) + 1
0136     error('Specified number sigma levels does not match supplied data')
0137 end
0138 if nSiglay ~= size(temp, 2) || size(siglay, 2) ~= size(temp, 2) || size(siglay, 2) ~= size(salt, 2)
0139     error('Specified number of sigma layers does not match supplied data')
0140 end
0141 
0142 
0143 %--------------------------------------------------------------------------
0144 % Set netCDF variables and dump to file
0145 %--------------------------------------------------------------------------
0146 
0147 % open boundary forcing
0148 nc = netcdf.create(tsOBCFile, 'clobber');
0149 
0150 % define global attributes
0151 netcdf.putAtt(nc,netcdf.getConstant('NC_GLOBAL'),'title','Open boundary temperature and salinity nudging')
0152 netcdf.putAtt(nc,netcdf.getConstant('NC_GLOBAL'),'type','FVCOM TIME SERIES OBC TS FILE')
0153 netcdf.putAtt(nc,netcdf.getConstant('NC_GLOBAL'),'history', sprintf('File created with %s from the MATLAB fvcom-toolbox', subname))
0154 
0155 
0156 % define dimensions
0157 nobc_dimid=netcdf.defDim(nc,'nobc',nObc);
0158 datestrlen_dimid=netcdf.defDim(nc,'DateStrLen',26);
0159 time_dimid=netcdf.defDim(nc,'time',netcdf.getConstant('NC_UNLIMITED'));
0160 siglay_dimid=netcdf.defDim(nc,'siglay',nSiglay);
0161 siglev_dimid=netcdf.defDim(nc,'siglev',nSiglev);
0162 
0163 % variables
0164 if strtime
0165     Times_varid=netcdf.defVar(nc,'Times','NC_CHAR',[datestrlen_dimid, time_dimid]);
0166     netcdf.putAtt(nc,Times_varid,'time_zone','UTC');
0167 end
0168 
0169 if floattime
0170     time_varid=netcdf.defVar(nc,'time','NC_FLOAT',time_dimid);
0171     netcdf.putAtt(nc,time_varid,'long_name','time');
0172     netcdf.putAtt(nc,time_varid,'units','days since 1858-11-17 00:00:00');
0173     netcdf.putAtt(nc,time_varid,'time_zone','UTC');
0174 end
0175 
0176 if inttime
0177     itime_varid=netcdf.defVar(nc,'Itime','NC_INT',time_dimid);
0178     netcdf.putAtt(nc,itime_varid,'units','days since 1858-11-17 00:00:00');
0179     netcdf.putAtt(nc,itime_varid,'format','modified julian day (MJD)');
0180     netcdf.putAtt(nc,itime_varid,'time_zone','UTC');
0181 
0182     itime2_varid=netcdf.defVar(nc,'Itime2','NC_INT',time_dimid);
0183     netcdf.putAtt(nc,itime2_varid,'units','msec since 00:00:00');
0184     netcdf.putAtt(nc,itime2_varid,'time_zone','UTC');
0185 end
0186 
0187 nobc_varid=netcdf.defVar(nc,'obc_nodes','NC_INT',nobc_dimid);
0188 netcdf.putAtt(nc,nobc_varid,'long_name','Open Boundary Node Number');
0189 netcdf.putAtt(nc,nobc_varid,'grid','obc_grid');
0190 netcdf.putAtt(nc,nobc_varid,'type','data');
0191 
0192 obc_h_varid=netcdf.defVar(nc,'obc_h','NC_FLOAT',nobc_dimid);
0193 netcdf.putAtt(nc,obc_h_varid,'long_name','Open Boundary Depth');
0194 netcdf.putAtt(nc,obc_h_varid,'units','m');
0195 netcdf.putAtt(nc,obc_h_varid,'grid','obc_grid');
0196 netcdf.putAtt(nc,obc_h_varid,'type','data');
0197 
0198 obc_siglev_varid=netcdf.defVar(nc,'siglev','NC_FLOAT',[nobc_dimid,siglev_dimid]);
0199 netcdf.putAtt(nc,obc_siglev_varid,'long_name','ocean_sigma/general_coordinate');
0200 netcdf.putAtt(nc,obc_siglev_varid,'grid','obc_grid');
0201 
0202 obc_siglay_varid=netcdf.defVar(nc,'siglay','NC_FLOAT',[nobc_dimid,siglay_dimid]);
0203 netcdf.putAtt(nc,obc_siglay_varid,'long_name','ocean_sigma/general_coordinate');
0204 netcdf.putAtt(nc,obc_siglay_varid,'grid','obc_grid');
0205 
0206 obc_temp_varid=netcdf.defVar(nc,'obc_temp','NC_FLOAT',[nobc_dimid,siglay_dimid,time_dimid]);
0207 netcdf.putAtt(nc,obc_temp_varid,'long_name','sea_water_temperature');
0208 netcdf.putAtt(nc,obc_temp_varid,'units','Celcius');
0209 netcdf.putAtt(nc,obc_temp_varid,'grid','obc_grid');
0210 
0211 obc_salinity_varid=netcdf.defVar(nc,'obc_salinity','NC_FLOAT',[nobc_dimid,siglay_dimid,time_dimid]);
0212 netcdf.putAtt(nc,obc_salinity_varid,'long_name','sea_water_salinity');
0213 netcdf.putAtt(nc,obc_salinity_varid,'units','PSU');
0214 netcdf.putAtt(nc,obc_salinity_varid,'grid','obc_grid');
0215 
0216 % end definitions
0217 netcdf.endDef(nc);
0218 
0219 % write data
0220 netcdf.putVar(nc,nobc_varid,obc_nodes);
0221 netcdf.putVar(nc,obc_h_varid,obc_h);
0222 netcdf.putVar(nc,obc_siglev_varid,siglev);
0223 netcdf.putVar(nc,obc_siglay_varid,siglay);
0224 if strtime
0225     nStringOut = char();
0226     [nYr, nMon, nDay, nHour, nMin, nSec] = mjulian2greg(time);
0227     for i=1:nTimes
0228         nDate = [nYr(i), nMon(i), nDay(i), nHour(i), nMin(i), nSec(i)];
0229         nStringOut = [nStringOut, sprintf('%04i/%02i/%02i %02i:%02i:%09.6f', nDate)];
0230     end
0231     netcdf.putVar(nc,Times_varid,[0, 0],[26, nTimes],nStringOut);
0232 end
0233 if floattime
0234     netcdf.putVar(nc,time_varid,0,numel(time),time);
0235 end
0236 if inttime
0237     netcdf.putVar(nc,itime_varid,floor(time));
0238     % netcdf.putVar(nc,itime2_varid,0,numel(time),mod(time,1)*24*3600*1000); % PWC original
0239     % KJA edit: avoids rounding errors when converting from double to single
0240     % Rounds to nearest multiple of the number of msecs in an hour
0241     netcdf.putVar(nc,itime2_varid,0,numel(time),round((mod(time,1)*24*3600*1000)/(3600*1000))*(3600*1000));
0242 end
0243 netcdf.putVar(nc,obc_temp_varid,temp);
0244 netcdf.putVar(nc,obc_salinity_varid,salt);
0245 
0246 % close file
0247 netcdf.close(nc);
0248 
0249 if ftbverbose
0250     fprintf('end   : %s\n', subname)
0251 end

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