function [zone,VARlist,auxdata] = tec2mat(fname,varargin)
%% load data file in Tecplot ASCII format
%% Author: Mach6
% Github repository: https://github.com/luohancfd/FluidDynamicTools/tree/master/Tecplot_Tools
% Method of calling:
% [zone,VARlist] = tec2mat(fname,debug);
% fname(in): name of data file
% optional flags:
% "debug" print zone information out (default: false)
% "safe" check the existence of scientific notation like 100-100 (default: false)
% For IJK ordered date only:
% "nopassive" include passive variables (0) in the data field (default: true)
% "passive" not include passive variables in the data field
% -------------------------------------------------------------------------
% ChangeLog:
% v1: support IJK data without mixing data format (node with cell-centered)
% support Finite Element grid
% v2: add a "safe" optional flag to handle number like 100-100 (100E-100)
%--------------------------------------------------------------------------
debug = false;
nopassive = true;
safe = false;
if nargin > 1
for i = 1:length(varargin)
if strcmp(varargin{i},'debug')
debug = true;
elseif strcmp(varargin{i},'nopassive')
nopassive = true;
elseif strcmp(varargin{i},'passive')
nopassive = false;
elseif strcmp(varargin{i},'safe')
safe = true;
else
error('Unknown option: %s',varargin{i})
end
end
end
%% First test if the file has "strange" scientific notations like 2.3-100 (2.3E-100)
if ~safe
IMY_FSCANF = false;
else
filetext = fileread(fname);
strange = regexp(filetext,'(?<!(?:(,|\[)))-?(\d+(\.\d+)?|\.\d+)([-+]\d+)','match','once');
if isempty(strange)
IMY_FSCANF = false;
else
IMY_FSCANF = true;
end
end
%% load tecplot ASCII file and write result to zone and VARList
fid = fopen(fname,'r');
NVAR = 0;
%% read file untill we get a line of variables name
IVAR = false;
varline = '';
while ~feof(fid)
pos = ftell(fid); %line above ZONE
line = fgetl(fid);
line = strtrim(line);
if ~isempty(line)
if (~strcmp(line(1),'#'))
if contains(line,'VARIABLES')
varnames = regexp(line,'VARIABLES\s*=\s*(.*)','tokens');
varline = [varline, varnames{1}{1}];
IVAR = true;
elseif (contains(line,'ZONE') || contains(line,'DATASETAUXDATA'))
fseek(fid,pos,-1); %jump out at position above zone
break
elseif (IVAR)
varline = [varline, line];
end
end
end
end
if debug
fprintf('===========================================\n');
fprintf('Read file: %s',fname);
end
if IVAR
varline0 = varline;
% replace all delimiter by a special symbol
varline = strrep(varline,'''','$#');
varline = strrep(varline,'"','$#');
varline = strrep(varline,',','$#');
VARlist0 =strsplit(varline,'$#');
VARlist = {};
for i = 1:length(VARlist0)
if ~isempty(strtrim(VARlist0{i}))
VARlist = [VARlist, VARlist0{i}];
end
end
NVAR = length(VARlist);
if debug
fprintf('The line defining variables:\n%s\n',varline0);
fprintf('The variables we get:\n');
fprintf('%s, ',VARlist{:});
fprintf('\n');
end
end
nzone = 0;
zone = [];
auxdata = {};
if ~IVAR
error("there is no variable list")
else
while ~feof(fid)
line = strtrim(fgetl(fid));
if ~isempty(line)
if strcmp(line(1),'#')
continue
end
end
if contains(upper(line),'DATASETAUXDATA')
if strcmpi(line(1:14),'DATASETAUXDATA')
line=strtrim(line(15:end));
temp = strsplit(line,'=');
temp(2)=strtrim(temp(2));
temp(2)=strrep(temp(2),'"','');
temp(2)=strrep(temp(2),'''','');
auxdata = [auxdata;{temp(1),temp(2)}];
end
end
if contains(line,'ZONE')
nzone = nzone + 1;
zoneline = regexp(line,'ZONE(.*)','tokens');
zoneline = strtrim(zoneline{1}{1});
while ~feof(fid)
pos = ftell(fid); %position above data
line = strtrim(fgetl(fid));
if ~isempty(line)
if strcmp(line(1),'#')
continue
end
end
if contains(line,'=')
zoneline = [zoneline,' ',line];
else
% arrive at data
fseek(fid,pos,-1); %jump out at position above zone
break
end
end
zoneline0 = zoneline;
% preprocess zone property, replace equal sign in quotes with a
% special symbol
quoted = regexp(zoneline,'"(.+?)"','tokenExtents');
quoteds = regexp(zoneline,'''(.+?)''','tokenExtents');
quoted = [quoted quoteds];
zoneline = '';
iendp = 1;
for i = 1:length(quoted)
istart = quoted{i}(1);
iend = quoted{i}(2);
if istart-1 >= iendp
zoneline = [zoneline,zoneline0(iendp:istart-1)];
end
zoneline = [zoneline,strrep(zoneline0(istart:iend),'=','$#')];
if iend == length(zoneline0)
break
end
iendp = iend+1;
end
if iend ~= length(zoneline0)
zoneline = [zoneline, zoneline0(iendp:end)];
end
% get zone properties
[ZONEprop.name,ZONEprop.start,ZONEprop.end] = regexp(zoneline,'\w+(?=\s*=)\s*=','match','start','end');
Nzoneprop = length(ZONEprop.name);
ZONEprop.prop = cell(1,Nzoneprop);
for i = 1:Nzoneprop-1
ZONEprop.name{i} = strtrim(ZONEprop.name{i}(1:end-1)); %remove "=" sign
ZONEprop.name{i} = upper(ZONEprop.name{i}); %upper case
if strcmpi(ZONEprop.name{i},'Nodes')
ZONEprop.name{i} = 'N';
end
if strcmpi(ZONEprop.name{i},'Elements')
ZONEprop.name{i} = 'E';
end
ZONEprop.prop{i} = strtrim(zoneline(ZONEprop.end(i)+1:ZONEprop.start(i+1)-1));
if strcmp(ZONEprop.prop{i}(end),',')
ZONEprop.prop{i} = ZONEprop.prop{i}(1:end-1);
end
end
ZONEprop.name{Nzoneprop} = strtrim(ZONEprop.name{Nzoneprop}(1:end-1));
ZONEprop.prop{Nzoneprop} = zoneline(ZONEprop.end(Nzoneprop)+1:end);
% reformat properties
Prop = [];
for i = 1:Nzoneprop
if isstrprop(ZONEprop.prop{i},'digit')
Prop.(ZONEprop.name{i}) = str2num(ZONEprop.prop{i});
else
Prop.(ZONEprop.name{i}) = strtrim(strrep(ZONEprop.prop{i},'$#','='));
end
end
clear ZONEprop;
if ~isfield(Prop,'T')
Prop.T = sprintf('ZONE %d',nzone);
else
if strcmp(Prop.T(1),'"') && strcmp(Prop.T(end),'"')
Prop.T = Prop.T(2:end-1);
elseif strcmp(Prop.T(1),'''') && strcmp(Prop.T(end),'''')
Prop.T = Prop.T(2:end-1);
end
end
Prop.title = Prop.T;
localVARindex = 1:NVAR;
if isfield(Prop,'PASSIVEVARLIST')
list = regexp(Prop.PASSIVEVARLIST,'[(.*)\]','tokens');
if ~isempty(list)
PASSIVE