Home > fvcom_prepro > read_gmsh_mesh.m

read_gmsh_mesh

PURPOSE ^

Read gmsh mesh files (version 2.2) into MATLAB mesh object.

SYNOPSIS ^

function [Mobj] = read_gmsh_mesh(varargin)

DESCRIPTION ^

 Read gmsh mesh files (version 2.2) into MATLAB mesh object.

 Mobj = function read_fvcom_mesh(varargin)

 DESCRIPTION:
    Read gmsh msh file and bathymetry file. Store in a matlab mesh object.

 INPUT [keyword pairs]:
   'msh'                   = gmsh msh file [e.g. casename.msh]
   [optional] 'bath'       = gmsh bathymetry file [e.g. tst_dep.dat]
   [optional] 'coordinate' = coordinate system [spherical; cartesian (default)]
   [optional] 'addCoriolis' = calculate Coriolis param (f), requires [lon, lat]

 OUTPUT:
    Mobj = MATLAB structure containing mesh data

 EXAMPLE USAGE
    Mobj = read_gmsh_mesh('msh', 'casename.msh', 'bath', 'bathy.dat')

 Author(s):
    Pierre Cazenave (Plymouth Marine Laboratory)

 Revision history

   2014-02-07 First version.

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

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [Mobj] = read_gmsh_mesh(varargin)
0002 % Read gmsh mesh files (version 2.2) into MATLAB mesh object.
0003 %
0004 % Mobj = function read_fvcom_mesh(varargin)
0005 %
0006 % DESCRIPTION:
0007 %    Read gmsh msh file and bathymetry file. Store in a matlab mesh object.
0008 %
0009 % INPUT [keyword pairs]:
0010 %   'msh'                   = gmsh msh file [e.g. casename.msh]
0011 %   [optional] 'bath'       = gmsh bathymetry file [e.g. tst_dep.dat]
0012 %   [optional] 'coordinate' = coordinate system [spherical; cartesian (default)]
0013 %   [optional] 'addCoriolis' = calculate Coriolis param (f), requires [lon, lat]
0014 %
0015 % OUTPUT:
0016 %    Mobj = MATLAB structure containing mesh data
0017 %
0018 % EXAMPLE USAGE
0019 %    Mobj = read_gmsh_mesh('msh', 'casename.msh', 'bath', 'bathy.dat')
0020 %
0021 % Author(s):
0022 %    Pierre Cazenave (Plymouth Marine Laboratory)
0023 %
0024 % Revision history
0025 %
0026 %   2014-02-07 First version.
0027 %
0028 %==============================================================================
0029 
0030 subname = 'read_gmsh_mesh';
0031 global ftbverbose
0032 if ftbverbose
0033     fprintf('\nbegin : %s \n', subname)
0034 end
0035 
0036 have_bath = false;
0037 have_strings = false;
0038 
0039 %--------------------------------------------------------------------------
0040 % Create a blank mesh object
0041 %--------------------------------------------------------------------------
0042 Mobj = make_blank_mesh;
0043 coordinate = 'cartesian';
0044 
0045 %--------------------------------------------------------------------------
0046 % Parse input arguments
0047 %--------------------------------------------------------------------------
0048 
0049 assert(mod(length(varargin), 2) == 0, 'incorrect usage of read_gmsh_mesh, use keyword pairs')
0050 
0051 % Assume we have nothing sensible.
0052 have_msh = false;
0053 have_bath = false;
0054 have_lonlat = false;
0055 have_xy = false;
0056 
0057 for i = 1:2:length(varargin) - 1
0058     keyword = lower(varargin{i});
0059 
0060     assert(ischar(keyword), 'incorrect usage of read_gmsh_mesh')
0061 
0062     switch keyword
0063         case 'msh'
0064             gmsh_msh = varargin{i + 1};
0065             have_msh = true;
0066         case 'bath'
0067             gmsh_bath = varargin{i + 1};
0068             have_bath = true;
0069         case 'coordinate'
0070             coord = varargin{i + 1};
0071             if strcmpi(coord, 'spherical')
0072                 coordinate = 'spherical';
0073                 have_lonlat = true;
0074             elseif strcmpi(coord, 'cartesian')
0075                 coordinate = 'cartesian';
0076                 have_xy = true;
0077             else
0078                 warning('Unrecognised coordinate system (%s). Valid values are ''spherical'' and ''cartesian''.', coordinate)
0079             end
0080         case 'addcoriolis'
0081             val = varargin{i + 1};
0082             if val
0083                 addCoriolis = true;
0084             else
0085                 addCoriolis = false;
0086             end
0087         otherwise
0088             disp(varargin{i + 1})
0089             error('Can''t understand property: %s', varargin{i + 1});
0090 
0091     end
0092 end
0093 
0094 %--------------------------------------------------------------------------
0095 % Read the mesh from the msh file
0096 %--------------------------------------------------------------------------
0097 
0098 fid = fopen(gmsh_msh, 'rt');
0099 assert(fid >= 0, sprintf('file: %s does not exist\n',  gmsh_msh));
0100 
0101 % Count number of elements and vertices
0102 if ftbverbose
0103     fprintf('Reading from: %s\n', gmsh_msh)
0104 end
0105 
0106 % Read mesh type, taken from:
0107 %
0108 % http://www.geuz.org/pipermail/gmsh/attachments/20071002/642cb6c3/attachment.m
0109 %
0110 
0111 lin = fgetl(fid);
0112 if strcmp(lin, '$NOD')
0113     fileformat = 1;
0114 elseif strcmp(lin, '$MeshFormat')
0115     fileformat = 2;
0116     lin = fgetl(fid);
0117     if feof(fid)
0118         fprintf(sprintf('Syntax error (no version) in: %s\n', filename));
0119         fileformat = 0;
0120     end
0121     form = sscanf(lin, '%f %d %d');
0122     if form(1) < 2
0123         fprintf(sprintf('Unknown mesh format: %s\n', lin));
0124         fileformat = 0;
0125     end
0126     if form(2) ~= 0
0127         fprintf('Sorry, this program can only read ASCII format\n');
0128         fileformat = 0;
0129     end
0130     fgetl(fid); % this should be $EndMeshFormat
0131     if feof(fid)
0132         fprintf('Syntax error (no $EndMeshFormat) in: %s\n', filename);
0133         fileformat = 0;
0134     end
0135     lin = fgetl(fid); % this should be $Nodes
0136     if feof(fid)
0137         fprintf('Syntax error (no $Nodes) in: %s\n', filename);
0138         fileformat = 0;
0139     end
0140 end
0141 
0142 assert(logical(fileformat), 'Unrecognised mesh.')
0143 % Read in the number of nodes
0144 nVerts = str2double(fgetl(fid));
0145 
0146 % Read the node positions.
0147 C = textscan(fid, '%d %f %f %f', nVerts);
0148 nid = C{1};
0149 x = C{2};
0150 y = C{3};
0151 z = C{4};
0152 
0153 if have_lonlat
0154     lon = x;
0155     lat = y;
0156 else
0157     lon = zeros(size(x));
0158     lat = zeros(size(y));
0159 end
0160 
0161 % Now we should be at the end of the nodes and about to read the elements.
0162 lin = fgetl(fid); lin = fgetl(fid); % need to skip one for some reason.
0163 assert(strcmp(lin, '$EndNodes'), 'Improperly formatted msh file.')
0164 lin = fgetl(fid);
0165 assert(strcmp(lin, '$Elements'), 'Improperly formatted msh file.')
0166 nElems = str2double(fgetl(fid));
0167 
0168 % Preallocate some arrays of use. We'll trim the NaNs later.
0169 tri12 = nan(nElems, 3);
0170 
0171 % Read the element triangulation table. Format is:
0172 %   ID, dim, n1, n2, n3[, n4]
0173 % If dim is 1, then n4 is omitted, otherwise if dim is 2, then we have an
0174 % extra link.
0175 c1 = 1;
0176 c2 = 1;
0177 for i = 1:nElems
0178     lin = fgetl(fid);
0179     C = regexpi(lin, ' ', 'split');
0180     if str2double(C(2)) == 1
0181         tri12(c1, :) = str2double(C(end-2:end));
0182         c1 = c1 + 1;
0183     elseif str2double(C(2)) == 2
0184         tri12(c2, :) = str2double(C(end-2:end));
0185         c2 = c2 + 1;
0186 %         else
0187 %             warning('Unsupported number of dimensions (up to 2).')
0188     end
0189 end
0190 tri1 = tri12(1:c1, :);
0191 tri2 = tri12(c1 + 1:c1 + c2, :);
0192 
0193 % Trim the excess NaNs
0194 tri2 = tri2(~isnan(tri2(:, 1)), :);
0195 
0196 % Reset the number of elements to the actual number of 2D ones.
0197 nElems = size(tri2, 1);
0198 
0199 have_lonlat = false;
0200 have_xy     = false;
0201 if strcmpi(coordinate, 'spherical')
0202     lon = x;
0203     lat = y;
0204     % Why reset everything to zero here?
0205     %x = x * 0.0;
0206     %y = y * 0.0;
0207     have_lonlat = true;
0208     % Just do a double check on the coordinates to make sure we don't
0209     % actually have cartesian
0210     if max(lon) > 360
0211         warning('You''ve specified spherical coordinates, but your upper longitude value exceeds 360 degrees. Are you sure you have spherical data?')
0212     end
0213 elseif strcmpi(coordinate, 'cartesian')
0214     have_xy = true;
0215 else
0216     warning('Unrecognised coordinate system (%s). Valid values are ''spherical'' and ''cartesian''.', coordinate)
0217 end
0218 
0219 fclose(fid);
0220 
0221 %--------------------------------------------------------------------------
0222 % Read the topography from the bathymetry file
0223 %--------------------------------------------------------------------------
0224 
0225 if have_bath
0226     bath_range = max(h) - min(h);
0227     if have_bath || bath_range == 0
0228         fid = fopen(gmsh_bath, 'rt');
0229         if fid < 0
0230             error('File: %s does not exist', gmsh_bath);
0231         else
0232             if ftbverbose; fprintf('reading gmsh bathymetry from: %s\n', gmsh_bath); end
0233         end
0234         lin = fgetl(fid);
0235         lin = fgetl(fid);
0236         lin = fgetl(fid);
0237         C = textscan(fid, '%s %d', 1);
0238         nVerts_tmp = C{2};
0239         C = textscan(fid, '%s %d', 1);
0240         nElems_tmp = C{2};
0241         if (nVerts - nVerts_tmp) * (nElems - nElems_tmp) ~= 0
0242             fprintf('Dimensions of bathymetry file do not match msh file\n')
0243             fprintf('Bathymetry nVerts: %d\n', nVerts_tmp)
0244             fprintf('Bathymetry nElems: %d\n', nElems_tmp)
0245             error('Stopping...')
0246         end
0247         lin = fgetl(fid);
0248         lin = fgetl(fid);
0249         lin = fgetl(fid);
0250         lin = fgetl(fid); % extra one for the new format from SMS 10.1, I think
0251         C2 = textscan(fid, '%f', nVerts);
0252         h = C2{1};
0253         have_bath = true;
0254 
0255         clear C2
0256     elseif bath_range ~= 0
0257         have_bath = true;
0258     end
0259 
0260     % Make sure we have positive depths
0261     if sum(h > 0) < sum(h < 0)
0262         h = -h;
0263     end
0264 end
0265 
0266 %--------------------------------------------------------------------------
0267 % Transfer to Mesh structure
0268 %--------------------------------------------------------------------------
0269 
0270 Mobj.nVerts  = nVerts;
0271 Mobj.nElems  = nElems;
0272 Mobj.nativeCoords = coordinate;
0273 
0274 if have_lonlat
0275     Mobj.have_lonlat    = have_lonlat;
0276 end
0277 if have_xy
0278     Mobj.have_xy        = have_xy;
0279 end
0280 if have_bath
0281     Mobj.have_bath      = have_bath;
0282     Mobj.h              = h;
0283 end
0284 if have_strings
0285     Mobj.have_strings   = have_strings;
0286     Mobj.read_obc_nodes = read_obc_nodes;
0287 end
0288 if exist('addCoriolis', 'var') && addCoriolis
0289     Mobj.have_cor       = true;
0290 end
0291 
0292 Mobj.x            = x;
0293 Mobj.y            = y;
0294 Mobj.z            = z; % for 3D grids
0295 Mobj.lon          = lon;
0296 Mobj.lat          = lat;
0297 Mobj.tri          = tri2;
0298 
0299 if ftbverbose
0300   fprintf('end   : %s\n', subname)
0301 end

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