ucftools/matlab/@ucf/ucf.m

827 lines
31 KiB
Matlab

classdef ucf < handle
% Low-level utilities for UCF files.
properties (Access = public)
File % file name
Type % file type
Class % file class
Endian % endianess
CodeVersion % version of the simulation code
UCFVersion % version of the data format ("unified container format")
NumDataset % maximum number of datasets in this file (over all time steps)
NumTimestep % number of time steps in this file
FileSize % file size
CreationTime % time of creation
IOMode % file opened in read-only or read-write mode?
IORank % rank of processor + col,row,pln
Verbosity % verbose output?
Debug % debug information?
end
properties (Access = private)
% File info
fileID
fileBeg
fileEnd
typeID
ioflag
tarflag
creationTimeUnix
versionMajor
versionMinor
versionPatch
versionFile
% Step pointers and info
posStep
numSetPerStep
timeStep
% Write-mode
isFileHeaderWritten
isStepHeaderWritten
% Current step information (should be resetable by resetCurrentStep())
currentStep
currentStepPosHeader
currentStepPosData
currentStepSize
currentStepTime
currentStepNumSet
% Current set information (should be resetable by resetCurrentSet())
currentSet
currentSetPosHeader
currentSetPosData
currentSetSize
currentSetDatatype
currentSetDatatypeNumeric
currentSetSizeof
currentSetNumParams
currentSetParams
currentSetNumElements
% Constants
magicFile = int64(81985529216486895);
magicStep = int64(11944304052957);
magicSet = int64(240217520921210);
nHeaderFile = 8;
nHeaderStep = 4;
nHeaderSet = 4;
nByteHeaderFile = 8;
nByteHeaderStep = 8;
nByteHeaderSet = 8;
nSetParamsField = 10;
nSetParamsParticle = 16;
factorMajor = 1000000000;
factorMinor = 1000000;
factorPatch = 1000;
factorTypeIDClass = 1000;
factorTypeIDKind = 10;
typeIDmatlabField = 1999;
typeIDmatlabParticle = 2999;
scanBuffSize = 4096;
end
%% ------------------------------------------------------------------------%%
%% CONSTRUCORS/DESTRUCTORS %%
%% ------------------------------------------------------------------------%%
methods(Access=public)
function obj = ucf(varargin)
% obj = ucf(varargin)
% Default contructor
% Input
% ? verbosity verbose output? (default: false)
% ? debug debug output? (default: false)
par = inputParser;
addParamValue(par,'verbosity',0,@isnumeric);
addParamValue(par,'debug',0,@isnumeric);
parse(par,varargin{:});
obj.resetPublicProperties();
obj.resetPrivateProperties();
obj.resetCurrentStep();
obj.resetCurrentSet();
obj.fileID = -1;
obj.tarflag = false;
obj.setVerbosity(par.Results.verbosity);
obj.setDebug(par.Results.debug);
end
function delete(obj)
% obj.delete()
% Default destructor
obj.close();
end
end
%% ------------------------------------------------------------------------%%
%% INITIALIZATION METHODS %%
%% ------------------------------------------------------------------------%%
methods(Access=public)
function open(obj,file)
% obj.open(file)
% Opens a file in read-only mode
obj.File = file; % add filename as object property
obj.IOMode = 'read'; % abstract IO mode
obj.ioflag = 'r'; % internal IO mode
obj.tarflag = false; % data is within a tar file?
% Try to open the file
obj.fileID = fopen(obj.File,obj.ioflag);
if obj.fileID<0
error('Unable to open file: %s',obj.File);
end
obj.fileBeg = ftell(obj.fileID);
fseek(obj.fileID,0,'eof');
obj.fileEnd = ftell(obj.fileID);
fseek(obj.fileID,0,'bof');
obj.FileSize = obj.fileEnd-obj.fileBeg;
% Read the file header
obj.readHeaderFile()
% Scan through file to get the basic structure (steps/sets)
obj.timeStep = zeros(1,obj.scanBuffSize,'double');
obj.posStep = zeros(1,obj.scanBuffSize,'double');
obj.numSetPerStep = zeros(1,obj.scanBuffSize,'double');
istep = 0;
while ftell(obj.fileID)<obj.FileSize
obj.readHeaderStep();
istep = istep+1;
obj.timeStep(istep) = obj.currentStepTime;
obj.posStep(istep) = ftell(obj.fileID);
obj.numSetPerStep(istep) = obj.currentStepNumSet;
if obj.currentStepSize==-1
break;
else
fseek(obj.fileID,obj.currentStepSize,'cof');
end
end
nstep = istep;
% Truncate buffered arrays
if nstep>obj.scanBuffSize
warning('Buffer overflow detected: increase scanBuffSize.');
end
obj.timeStep = obj.timeStep(1:nstep);
obj.posStep = obj.posStep(1:nstep);
obj.numSetPerStep = obj.numSetPerStep(1:nstep);
% Set some internal variables
obj.NumDataset = max(obj.numSetPerStep);
obj.NumTimestep = nstep;
obj.isFileHeaderWritten = true;
obj.isStepHeaderWritten = true;
end
function edit(obj,file)
% obj.edit(file)
% Opens a file in read-write mode
obj.File = file; % add filename as object property
obj.IOMode = 'edit'; % abstract IO mode
obj.ioflag = 'r+'; % internal IO mode
obj.tarflag = false; % data is within a tar file?
% Try to open the file
obj.fileID = fopen(obj.File,obj.ioflag);
if obj.fileID<0
error('Unable to open file: %s',obj.File);
end
obj.fileBeg = ftell(obj.fileID);
fseek(obj.fileID,0,'eof');
obj.fileEnd = ftell(obj.fileID);
fseek(obj.fileID,0,'bof');
obj.FileSize = obj.fileEnd-obj.fileBeg;
% Read the file header
obj.readHeaderFile()
% Scan through file to get the basic structure (steps/sets)
obj.timeStep = zeros(1,obj.scanBuffSize,'double');
obj.posStep = zeros(1,obj.scanBuffSize,'double');
obj.numSetPerStep = zeros(1,obj.scanBuffSize,'double');
istep = 0;
while ftell(obj.fileID)<obj.FileSize
obj.readHeaderStep();
istep = istep+1;
obj.timeStep(istep) = obj.currentStepTime;
obj.posStep(istep) = ftell(obj.fileID);
obj.numSetPerStep(istep) = obj.currentStepNumSet;
if obj.currentStepSize==-1
break;
else
fseek(obj.fileID,obj.currentStepSize,'cof');
end
end
nstep = istep;
% Truncate buffered arrays
if nstep>obj.scanBuffSize
warning('Buffer overflow detected: increase scanBuffSize.');
end
obj.timeStep = obj.timeStep(1:nstep);
obj.posStep = obj.posStep(1:nstep);
obj.numSetPerStep = obj.numSetPerStep(1:nstep);
% Set some internal variables
obj.NumDataset = max(obj.numSetPerStep);
obj.NumTimestep = nstep;
obj.isFileHeaderWritten = true;
obj.isStepHeaderWritten = true;
end
function create(obj,file,varargin)
% obj.create(file,varargin)
% Creates a new file and writes file header
% Input
% file file name/path
% ? type file type {'field' (default),'particle'}
% ? rank proc rank (default: [0,0,0,0])
% ? endian endianess {'n' (dafault),'a','l','s','b'}
par = inputParser;
addParamValue(par,'type','field',@ischar);
addParamValue(par,'rank',[0,0,0,0],@(x)(isnumeric(x)&&numel(x)==4));
addParamValue(par,'endian','n',@ischar);
parse(par,varargin{:});
%
obj.File = file; % add filename as object property
obj.IOMode = 'create'; % abstract IO mode
obj.ioflag = 'w+'; % internal IO mode
obj.tarflag = false; % data is within a tar file?
obj.isFileHeaderWritten = false;
obj.isStepHeaderWritten = false;
% Try to create the file
obj.fileID = fopen(obj.File,obj.ioflag);
if obj.fileID<0
error('Unable to create file: %s',obj.File);
end
obj.fileBeg = ftell(obj.fileID);
obj.fileEnd = ftell(obj.fileID);
obj.FileSize = obj.fileEnd-obj.fileBeg;
switch par.Results.type
case 'field'
obj.typeID = obj.typeIDmatlabField;
obj.Class = 'field';
case 'particle'
obj.typeID = obj.typeIDmatlabParticle;
obj.Class = 'particle';
otherwise
error('Unknown file type: %s',par.Results.type);
end
obj.IORank = par.Results.rank;
obj.Endian = par.Results.endian;
obj.versionMajor = 0;
obj.versionMinor = 0;
obj.versionPatch = 0;
obj.versionFile = 1;
obj.writeHeaderFile();
end
function opentar(obj,ptr)
% obj.opentar(ptr)
% Opens a subfile from tar in read-only mode
obj.File = 'tar-mode'; % Set generic file name
obj.IOMode = 'read'; % abstract IO mode
obj.ioflag = 'r'; % internal IO mode
obj.tarflag = true; % data is within a tar file?
% Set file ID to tar file ID
obj.fileID = ptr(1);
if obj.fileID<0
error('Unable to access file: %s',obj.File);
end
obj.fileBeg = ptr(2);
obj.fileEnd = ptr(2)+ptr(3);
obj.FileSize = ptr(3);
% Read the file header
obj.readHeaderFile()
% Scan through file to get the basic structure (steps/sets)
obj.timeStep = zeros(1,obj.scanBuffSize,'double');
obj.posStep = zeros(1,obj.scanBuffSize,'double');
obj.numSetPerStep = zeros(1,obj.scanBuffSize,'double');
istep = 0;
while ftell(obj.fileID)<obj.fileEnd
obj.readHeaderStep();
istep = istep+1;
obj.timeStep(istep) = obj.currentStepTime;
obj.posStep(istep) = ftell(obj.fileID);
obj.numSetPerStep(istep) = obj.currentStepNumSet;
if obj.currentStepSize==-1
break;
else
fseek(obj.fileID,obj.currentStepSize,'cof');
end
end
nstep = istep;
% Truncate buffered arrays
if nstep>obj.scanBuffSize
warning('Buffer overflow detected: increase scanBuffSize.');
end
obj.timeStep = obj.timeStep(1:nstep);
obj.posStep = obj.posStep(1:nstep);
obj.numSetPerStep = obj.numSetPerStep(1:nstep);
% Set some internal variables
obj.NumDataset = max(obj.numSetPerStep);
obj.NumTimestep = nstep;
obj.isFileHeaderWritten = true;
obj.isStepHeaderWritten = true;
end
end
%% ------------------------------------------------------------------------%%
%% PUBLIC METHODS %%
%% ------------------------------------------------------------------------%%
methods(Access=public)
function close(obj)
% obj.close()
% Closes a file
obj.resetPublicProperties();
obj.resetPrivateProperties();
obj.resetCurrentStep();
obj.resetCurrentSet();
if obj.tarflag
obj.tarflag = false;
obj.fileID = -1;
return;
end
if obj.fileID<0
return;
end
status = fclose(obj.fileID);
if status<0
warning('Unable to close file (exit code: %d)',status);
return;
end
obj.fileID = -1;
end
function [isType] = validateType(obj,type)
switch type
case 'grid'
isType = (obj.typeID==0);
case 'procgrid'
isType = (obj.typeID==10);
case 'field'
isType = (floor(obj.typeID/obj.factorTypeIDClass)==1);
case 'particle'
isType = (floor(obj.typeID/obj.factorTypeIDClass)==2);
case 'snapshot'
isType = (mod(obj.typeID,obj.factorTypeIDKind)==0);
case 'append'
isType = (mod(obj.typeID,obj.factorTypeIDKind)==1);
case {'uvwp','fluid'}
isType = (obj.typeID==1000);
case 'scalar'
isType = (obj.typeID==1010);
case 'matlab'
isType = (mod(obj.typeID,obj.factorTypeIDKind)==9);
otherwise
error('Unknown type: %s',type);
end
end
% ------------------------------------------------------------------------%
% Read %
% ------------------------------------------------------------------------%
function [data,params] = readSet(obj,tstep,dset)
% [data,params] = obj.readSet(tstep,dset)
% Reads a raw dataset from file (no reshaping or parsing of parameters)
% Input
% tstep index of timestep to be read
% dset index of dataset to be read
% Output
% data raw data with dim(1,nelements)
% params raw parameters with dim(1,nparams)
fseek(obj.fileID,obj.findSet(tstep,dset),'bof');
obj.readHeaderSet();
params = obj.currentSetParams;
data = fread(obj.fileID,[1,obj.currentSetNumElements],...
[obj.currentSetDatatype,'=>',obj.currentSetDatatype]);
end
function [params] = readParameters(obj,tstep,dset)
% [params] = obj.readParameters(tstep,dset)
% Reads a raw set of parameters without parsing.
% Input
% tstep index of timestep to be read
% dset index of dataset to be read
% Output
% params raw parameters with dim(1,nparams)
fseek(obj.fileID,obj.findSet(tstep,dset),'bof');
if obj.Debug
fprintf('Skipped to position %d\n',ftell(obj.fileID));
end
obj.readHeaderSet();
params = obj.currentSetParams;
end
% ------------------------------------------------------------------------%
% Append %
% ------------------------------------------------------------------------%
function appendStep(obj,time)
% [] = obj.appendStep(time)
% Creates a new step at the end of opened file.
% Input
% time simulation time
if ~obj.verifyWriteMode()
error('File must be opened in create/edit mode.');
end
%
obj.resetCurrentStep();
obj.resetCurrentSet();
%
fseek(obj.fileID,0,'eof');
obj.currentStep = obj.NumTimestep+1;
obj.currentStepPosHeader = ftell(obj.fileID);
obj.currentStepSize = 0;
obj.currentStepTime = time;
obj.currentStepNumSet = 0;
obj.writeHeaderStep();
obj.currentStepPosData = ftell(obj.fileID);
obj.currentSet = 0;
%
obj.NumTimestep = obj.currentStep;
obj.posStep(obj.currentStep) = obj.currentStepPosData;
obj.numSetPerStep(obj.currentStep) = obj.currentStepNumSet;
obj.timeStep(obj.currentStep) = obj.currentStepTime;
%
if obj.Verbosity
fprintf('Created timestep #%d with time = %f\n',obj.NumTimestep,obj.currentStepTime);
end
end
function appendSet(obj,data,params)
% [] = obj.appendSet(data,params)
% Creates a new dataset at the end of opened file and writes data.
% Input
% data data to append
% parameters dataset header parameters
if ~obj.verifyWriteMode()
error('File must be opened in create/edit mode.');
end
% Evaluate datatype
obj.currentSetDatatype = class(data);
switch obj.currentSetDatatype
case 'int32'; obj.currentSetDatatypeNumeric = 11; obj.currentSetSizeof = 4;
case 'int64'; obj.currentSetDatatypeNumeric = 12; obj.currentSetSizeof = 8;
case 'single'; obj.currentSetDatatypeNumeric = 21; obj.currentSetSizeof = 4;
case 'double'; obj.currentSetDatatypeNumeric = 22; obj.currentSetSizeof = 8;
otherwise
error('Datatype not implemented: %s',obj.currentSetDatatype);
end
% Append a new set header
fseek(obj.fileID,0,'eof');
obj.currentSet = obj.numSetPerStep(obj.currentStep)+1;
obj.currentSetPosHeader = ftell(obj.fileID);
obj.currentSetSize = numel(data)*obj.currentSetSizeof;
switch obj.Class
case 'field'; obj.currentSetNumParams = obj.nSetParamsField;
case 'particle'; obj.currentSetNumParams = obj.nSetParamsParticle;
otherwise; error('Invalid file class: %s',obj.Class);
end
obj.currentSetParams = zeros(1,obj.currentSetNumParams,'int64');
obj.currentSetParams(1:numel(params)) = params;
obj.writeHeaderSet();
% Append actual data
obj.currentSetPosData = ftell(obj.fileID);
fwrite(obj.fileID,data(:),obj.currentSetDatatype,0,obj.Endian);
% Rewrite step header
obj.currentStepNumSet = obj.currentStepNumSet+1;
obj.currentStepSize = obj.currentStepSize+...
(4+obj.currentSetNumParams)*obj.nByteHeaderStep+...
obj.currentSetSize;
obj.writeHeaderStep();
% Update internal variables
obj.numSetPerStep(obj.currentStep) = obj.currentSet;
obj.NumDataset = max(obj.currentSet,obj.NumDataset);
% Verbose output
if obj.Verbosity
fprintf('Created dataset %d at timestep #%d\n',obj.currentSet,obj.currentStep);
end
end
function exchangeSet(obj,istep,iset,data)
% [] = obj.exchangeSet(istep,iset,data)
% Exchanges the data stored in dataset (istep,iset) with the data provided.
% Input
% data data, which replaces dataset (must be same size and type)
if ~obj.verifyWriteMode()
error('File must be opened in create/edit mode.');
end
% Evaluate datatype and datasize
dtype = class(data);
switch dtype
case 'int32'; dtypeNumeric = 11; dtypeSizeof = 4;
case 'int64'; dtypeNumeric = 12; dtypeSizeof = 8;
case 'single'; dtypeNumeric = 21; dtypeSizeof = 4;
case 'double'; dtypeNumeric = 22; dtypeSizeof = 8;
otherwise
error('Datatype not implemented: %s',dtype);
end
dsize = numel(data)*dtypeSizeof;
% Navigate to correct dataset
fseek(obj.fileID,obj.findSet(istep,iset),'bof');
obj.readHeaderSet();
% Check if datatype/datasize match
if dtypeNumeric~=obj.currentSetDatatypeNumeric
error('Datatype mismatch: %s,%s',dtype,obj.currentSetDatatype)
end
if dsize~=obj.currentSetSize
error('Datasize mismatch: %d,%d',dsize,obj.currentSetSize)
end
% Write data
fwrite(obj.fileID,data(:),obj.currentSetDatatype,0,obj.Endian);
% Verbose output
if obj.Verbosity
fprintf('Edited dataset %d at timestep #%d\n',obj.currentSet,obj.currentStep);
end
end
% ------------------------------------------------------------------------%
% Setter %
% ------------------------------------------------------------------------%
function setVerbosity(obj,flag)
% obj.setVerbosity(flag)
% Sets verbosity
% Input
% flag '1' -> verbose output
obj.Verbosity = flag;
end
function setDebug(obj,flag)
% obj.setDebug(flag)
% Sets debug flag
% Input
% flag '1' -> debug output
obj.Debug = flag;
end
% ------------------------------------------------------------------------%
% Getter %
% ------------------------------------------------------------------------%
function [nstep] = getNumTimesteps(obj)
% [nstep] = obj.getNumTimesteps()
% Gets total number of time steps.
nstep = obj.NumTimestep;
end
function [stime] = getSimulationTime(obj,varargin)
% [stime] = obj.getSimulationTime(varargin)
% Gets simulation time for one/all time steps
% Input
% ? istep step index (default: -1, all steps)
par = inputParser;
addParamValue(par,'istep',-1,@isnumeric);
parse(par,varargin{:});
if par.Results.istep==-1
stime = obj.timeStep;
else
stime = obj.timeStep(par.Results.istep);
end
end
function [ndset] = getNumDatasets(obj,istep)
% [ndset] = obj.getNumDatasets(istep)
% Gets number datasets for a given time step.
% Input
% istep step index
ndset = obj.numSetPerStep(istep);
end
function [dpos,dsize,dtype,dnum] = getDataSetPosition(obj,tstep,dset)
% [params] = obj.readParameters(tstep,dset)
% Reads a raw set of parameters without parsing.
% Input
% tstep index of timestep to be read
% dset index of dataset to be read
% Output
% fpos offset to beginning of dataset
fseek(obj.fileID,obj.findSet(tstep,dset),'bof');
if obj.Debug
fprintf('Skipped to position %d\n',ftell(obj.fileID));
end
obj.readHeaderSet();
dpos = ftell(obj.fileID);
dsize = obj.currentSetSize;
dtype = obj.currentSetDatatype;
dnum = obj.currentSetNumElements;
end
end
%% ------------------------------------------------------------------------%%
%% PRIVATE METHODS %%
%% ------------------------------------------------------------------------%%
methods (Access = private)
function readHeaderFile(obj)
% Skip to beginning of file
fseek(obj.fileID,obj.fileBeg,'bof');
% Determine endianess
mfmt = 'aslb';
for fmt=mfmt
currentMagic = fread(obj.fileID,1,'int64=>int64',0,fmt);
fseek(obj.fileID,obj.fileBeg,'bof');
if currentMagic==obj.magicFile
break;
end
end
if currentMagic~=obj.magicFile
error('Magic mismatch: invalid file header. %d',currentMagic);
end
obj.Endian = fmt;
% Read header
header = fread(obj.fileID,[1,obj.nHeaderFile],'int64=>int64',0,obj.Endian);
if obj.Debug
fprintf('Read the following file header at %d bytes\n',0);
fprintf('%d,%d,%d,%d,%d,%d,%d,%d\n',header);
end
% Parse version
obj.versionMajor = floor(double(header(2))/obj.factorMajor);
obj.versionMinor = floor(mod(double(header(2)),obj.factorMajor)/obj.factorMinor);
obj.versionPatch = floor(mod(double(header(2)),obj.factorMinor)/obj.factorPatch);
obj.CodeVersion = sprintf('%d.%d.%d',obj.versionMajor,obj.versionMinor,obj.versionPatch);
obj.UCFVersion = mod(double(header(2)),obj.factorPatch);
% Parse time stamp (UTC)
obj.creationTimeUnix = double(header(3));
obj.CreationTime = datestr(obj.creationTimeUnix/86400 + datenum(1970,1,1));
% Parse file type
obj.typeID = double(header(4));
switch obj.typeID
case 0000; obj.Type = 'grid';
case 0010; obj.Type = 'processor grid';
case 1000; obj.Type = 'fluid snapshot';
case 1010; obj.Type = 'scalar snapshot';
case 1999; obj.Type = 'matlab field data';
case 2000; obj.Type = 'particle snapshot';
case 2001; obj.Type = 'particle append';
case 2011; obj.Type = 'particle lagrange';
case 2021; obj.Type = 'particle balancing';
case 2999; obj.Type = 'matlab particle data';
case 3000; obj.Type = 'statistics fluid';
case 3010; obj.Type = 'statistics fluid pure';
case 3020; obj.Type = 'statistics scalar';
otherwise; obj.Type = 'unknown';
end
% Parse file class
switch floor(obj.typeID/obj.factorTypeIDClass)
case 1; obj.Class = 'field';
case 2; obj.Class = 'particle';
case 3; obj.Class = 'statistics';
otherwise; obj.Class = 'unknown';
end
% Parse IO rank
obj.IORank = double(header(5:8));
end
function readHeaderStep(obj)
% Read and parse
obj.currentStepPosHeader = ftell(obj.fileID);
header = fread(obj.fileID,[1,obj.nHeaderStep],'int64=>int64',0,obj.Endian);
obj.currentStepPosData = ftell(obj.fileID);
currentMagic = header(1);
obj.currentStepSize = double(header(2));
obj.currentStepTime = typecast(header(3),'double');
obj.currentStepNumSet = double(header(4));
if obj.Debug
fprintf('Read the following step header at %d bytes\n',obj.currentStepPosHeader);
fprintf('%d,%d,%f,%d\n',header(1),header(2),typecast(header(3),'double'),header(4));
end
% Check if magic is correct
if currentMagic~=obj.magicStep
error('Magic mismatch: invalid step header. %d',currentMagic);
end
end
function readHeaderSet(obj)
% Read and parse
obj.currentSetPosHeader = ftell(obj.fileID);
header = fread(obj.fileID,[1,obj.nHeaderSet],'int64=>int64',0,obj.Endian);
obj.currentSetPosData = ftell(obj.fileID);
currentMagic = header(1);
obj.currentSetSize = double(header(2));
obj.currentSetDatatypeNumeric = double(header(3));
switch obj.currentSetDatatypeNumeric
case 11; obj.currentSetSizeof = 4; obj.currentSetDatatype = 'int32';
case 12; obj.currentSetSizeof = 8; obj.currentSetDatatype = 'int64';
case 21; obj.currentSetSizeof = 4; obj.currentSetDatatype = 'single';
case 22; obj.currentSetSizeof = 8; obj.currentSetDatatype = 'double';
otherwise
error('Unknown datatype: %d',obj.currentSetDatatypeNumeric);
end
obj.currentSetNumParams = double(header(4));
obj.currentSetNumElements = round(obj.currentSetSize/obj.currentSetSizeof);
if obj.Debug
fprintf('Read the following set header at %d bytes\n',obj.currentSetPosHeader);
fprintf('%d,%d,%d,%d\n',header(1),header(2),header(3),header(4));
end
% Check if magic is correct
if currentMagic~=obj.magicSet
error('Magic mismatch: invalid dataset header. %d',currentMagic);
end
% Read variable number of parameters
obj.currentSetParams = fread(obj.fileID,[1,obj.currentSetNumParams],'int64=>int64',0,obj.Endian);
if obj.Debug
fprintf('with parameters:')
for ii=1:obj.currentSetNumParams
fprintf(' %d',obj.currentSetParams(ii));
end
fprintf('\n');
end
end
function [flag] = verifyWriteMode(obj)
flag = false;
switch obj.IOMode
case {'edit','create'}
flag = true;
end
end
function writeHeaderFile(obj)
obj.creationTimeUnix = int64(java.lang.System.currentTimeMillis/1000); % using java for compatability before Matlab2014a
header = zeros(1,obj.nHeaderFile,'int64');
header(1) = obj.magicFile;
header(2) = obj.versionMajor*obj.factorMajor + ...
obj.versionMinor*obj.factorMinor + ...
obj.versionPatch*obj.factorPatch + ...
obj.versionFile;
header(3) = obj.creationTimeUnix;
header(4) = int64(obj.typeID);
header(5:8) = int64(obj.IORank);
fseek(obj.fileID,obj.fileBeg,'bof');
if obj.Debug
fprintf('Writing the following file header at %d bytes\n',ftell(obj.fileID));
fprintf('%d,%d,%d,%d,%d,%d,%d,%d\n',header);
end
fwrite(obj.fileID,header,'int64',0,obj.Endian);
obj.isFileHeaderWritten = true;
end
function writeHeaderStep(obj)
if ~obj.isFileHeaderWritten
error('No file header has been written yet.');
end
fseek(obj.fileID,obj.currentStepPosHeader,'bof');
if obj.Debug
fprintf('Writing the following step header at %d bytes\n',ftell(obj.fileID));
fprintf('%d,%d,%f,%d\n',obj.magicStep,obj.currentStepSize,obj.currentStepTime,obj.currentStepNumSet);
end
fwrite(obj.fileID,obj.magicStep,'int64',0,obj.Endian);
fwrite(obj.fileID,obj.currentStepSize,'int64',0,obj.Endian);
fwrite(obj.fileID,obj.currentStepTime,'double',0,obj.Endian);
fwrite(obj.fileID,obj.currentStepNumSet,'int64',0,obj.Endian);
obj.isStepHeaderWritten = true;
end
function writeHeaderSet(obj)
if ~obj.isStepHeaderWritten
error('No step header has been written yet.');
end
fseek(obj.fileID,obj.currentSetPosHeader,'bof');
header = zeros(1,obj.nHeaderSet,'int64');
header(1) = obj.magicSet;
header(2) = obj.currentSetSize;
header(3) = obj.currentSetDatatypeNumeric;
header(4) = obj.currentSetNumParams;
obj.currentSetParams = obj.currentSetParams(1:obj.currentSetNumParams);
if obj.Debug
fprintf('Writing the following set header at %d bytes\n',ftell(obj.fileID));
fprintf('%d,%d,%d,%d\n',header);
fprintf('with parameters:')
for ii=1:obj.currentSetNumParams
fprintf(' %d',obj.currentSetParams(ii));
end
fprintf('\n');
end
fwrite(obj.fileID,header,'int64',0,obj.Endian);
fwrite(obj.fileID,obj.currentSetParams,'int64',0,obj.Endian);
end
function [posHeader] = findSet(obj,tstep,dset)
% Check input
if tstep>obj.NumTimestep
error('Out of bounds: timestep. %d, %d',tstep,obj.NumTimestep);
end
if dset>obj.numSetPerStep(tstep)
error('Out of bounds: dataset. %d, %d',dset,obj.NumDataset);
end
% Navigate to correct set
fseek(obj.fileID,obj.posStep(tstep),'bof');
for iset=1:dset-1
obj.readHeaderSet();
fseek(obj.fileID,obj.currentSetSize,'cof');
end
posHeader = ftell(obj.fileID);
if obj.Debug
fprintf('Found step #%d, set #%d at position %d\n',tstep,dset,posHeader)
end
end
function resetPublicProperties(obj)
obj.File = [];
obj.Type = [];
obj.Class = [];
obj.Endian = [];
obj.CodeVersion = [];
obj.UCFVersion = [];
obj.NumDataset = [];
obj.NumTimestep = [];
obj.FileSize = [];
obj.CreationTime = [];
obj.IOMode = [];
obj.IORank = [];
obj.Verbosity = [];
obj.Debug = [];
end
function resetPrivateProperties(obj)
obj.fileBeg = [];
obj.fileEnd = [];
obj.typeID = [];
obj.ioflag = [];
obj.creationTimeUnix = [];
obj.versionMajor = [];
obj.versionMinor = [];
obj.versionPatch = [];
obj.versionFile = [];
obj.posStep = [];
obj.numSetPerStep = [];
obj.timeStep = [];
obj.isFileHeaderWritten = [];
obj.isStepHeaderWritten = [];
end
function resetCurrentStep(obj)
obj.currentStep = [];
obj.currentStepPosHeader = [];
obj.currentStepPosData = [];
obj.currentStepSize = [];
obj.currentStepTime = [];
obj.currentStepNumSet = [];
end
function resetCurrentSet(obj)
obj.currentSet = [];
obj.currentSetPosHeader = [];
obj.currentSetPosData = [];
obj.currentSetSize = [];
obj.currentSetDatatype = [];
obj.currentSetDatatypeNumeric = [];
obj.currentSetSizeof = [];
obj.currentSetNumParams = [];
obj.currentSetParams = [];
obj.currentSetNumElements = [];
end
end
end