diff --git a/src/genInputParsers.m b/src/genInputParsers.m new file mode 100644 index 0000000..d2e71f8 --- /dev/null +++ b/src/genInputParsers.m @@ -0,0 +1,192 @@ +function IP =genInputParsers + IP.INFORMATION = parseINFORMATION(); + IP.INITIAL_GEOMETRY_DEFINITION = parseINITIAL_GEOMETRY_DEFINITION(); + IP.STEP = parseSTEP(); + IP.SOLUTION_CONTROL = parseSOLUTION_CONTROL(); + IP.LINEAR_SOLVE = parseLINEAR_SOLVE(); + IP.TIME_CONTROL = parseTIME_CONTROL(); + IP.FLOW_DEFINITION = parseFLOW_DEFINITION(); + IP.REYNOLDS = parseREYNOLDS(); + IP.CIRCULATION = parseCIRCULATION(); + IP.RESULT = parseRESULT(); + IP.LOG_INFO = parseLOG_INFO(); + IP.IN_SITU = parseIN_SITU(); +end + +%% +function IP = parseINFORMATION +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +end + +%% +function IP = parseINITIAL_GEOMETRY_DEFINITION +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addRequired(IP,'nx',@(x)validateattributes(x,'double',{'scalar','integer','>',4})) +addRequired(IP,'ny',@(x)validateattributes(x,'double',{'scalar','integer','>',4})) +addRequired(IP,'xmin',@(x)validateattributes(x,'double',{'isfinite','isreal'})) +addRequired(IP,'xmax',@(x)validateattributes(x,'double',{'isfinite','isreal'})) +addRequired(IP,'ymin',@(x)validateattributes(x,'double',{'isfinite','isreal'})) +addRequired(IP,'ymax',@(x)validateattributes(x,'double',{'isfinite','isreal'})) +end + +%% +function IP = parseSTEP +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +% +addRequired(IP,'SOLUTION_CONTROL',@(x)validateattributes(x,{'struct'})) +addRequired(IP,'FLOW_DEFINITION',@(x)validateattributes(x,{'struct'})) +addOptional(IP,'RESULT',@(x)validateattributes(x,{'struct'})) +addOptional(IP,'LOG_INFO',@(x)validateattributes(x,{'struct'})) +addOptional(IP,'IN_SITU',@(x)validateattributes(x,{'struct'})) +end + +%% +function IP = parseSOLUTION_CONTROL +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addParameter(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addParameter(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +% +addRequired(IP,'LINEAR_SOLVE',@(x)validateattributes(x,{'struct'})) +addRequired(IP,'TIME_CONTROL',@(x)validateattributes(x,{'struct'})) +end + +%% +function IP = parseLINEAR_SOLVE +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +Solvers = {"Jacobi", "PCG","GMRES","Direct","Linfactor","Inverse"}; +Hardware = {"CPU", "GPU"}; +Preconditioners = {"ILU"}; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addParameter(IP,'relTol',1e-5,@(x)validateattributes(x,{'double'},{'positive'})) +addParameter(IP,'maxIter',1e3,@(x)validateattributes(x,{'double'},{'positive','integer'})) +addParameter(IP,'solver',"Jacobi",@(x)validatestring(x,Solvers)) +addParameter(IP,'hardware',"CPU",@(x)validatestring(x,Hardware)) + +addOptional(IP,'preconditioner',@(x)validatestring(x,Preconditioners)) +addOptional(IP,'kspace',@(x)validateattributes(x,{'double'},{'positive','integer'})) +end + +%% +function IP = parseTIME_CONTROL +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +end + +%% +function IP = parseFLOW_DEFINITION +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +% +addRequired(IP,'REYNOLDS',@(x)validateattributes(x,{'struct'})) +addRequired(IP,'CIRCULATION',@(x)validateattributes(x,{'struct'})) +end + +%% +function IP = parseREYNOLDS +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +funcTypes = {'constant'}; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addRequired(IP,'func',@(x)validatestring(x,{'string'},funcTypes)) +addRequired(IP,'value',@(x)validateattributes(x,{'double'},{'positive','finite'})) +addParameter(IP,'scale',@(x)validateattributes(x,{'double'},{'positive','finite'})) +end + +%% +function IP = parseCIRCULATION +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +end + +%% +function IP = parseRESULT +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +end + +%% +function IP = parseLOG_INFO +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +end + +%% +function IP = parseIN_SITU +IP = inputParser; +IP.CaseSensitive = false; +IP.KeepUnmatched = false; +IP.PartialMatching = false; +IP.StructExpand = true; +% +addOptional(IP,'title','',@(x)validateattributes(x,{'string'},{'nonempty'})) +addOptional(IP,'description','',@(x)validateattributes(x,{'string'},{'nonempty'})) +end diff --git a/src/generateLegalParameters.m b/src/generateLegalParameters.m index 94f5e6e..bd3123b 100644 --- a/src/generateLegalParameters.m +++ b/src/generateLegalParameters.m @@ -1,125 +1,210 @@ -function PARAM = generateLegalParameters +function pGraph = generateLegalParameters %% -simTitle = struct('name','title','class','char','isRequired',false); +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); INFORMATION.Children = []; -INFORMATION.Variables = struct('simTitle',simTitle); +INFORMATION.Variables = struct('title',blockTitle,'description',description); INFORMATION.isRequired = false; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); nx = struct('name','nx','class',{'double'},'isRequired',true); ny = struct('name','ny','class',{'double'},'isRequired',true); - xmin = struct('name','xmin','class',{'double'},'isRequired',true); xmax = struct('name','xmax','class',{'double'},'isRequired',true); ymin = struct('name','ymin','class',{'double'},'isRequired',true); ymax = struct('name','ymax','class',{'double'},'isRequired',true); -GEOMETRY_DEFINITION.Children = []; -GEOMETRY_DEFINITION.Variables = struct('nx',nx,'ny',ny,'xmin',xmin,'xmax',xmax,'ymin',ymin,'ymax',ymax); -GEOMETRY_DEFINITION.isRequired = true; +INITIAL_GEOMETRY_DEFINITION.Children = []; +INITIAL_GEOMETRY_DEFINITION.Variables = struct('title',blockTitle,'description',description,... + 'nx',nx,'ny',ny,... + 'xmin',xmin,'xmax',xmax,... + 'ymin',ymin,'ymax',ymax); +INITIAL_GEOMETRY_DEFINITION.isRequired = true; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); relTol = struct('name','relative tolerance','class',{'double'},'isRequired',false,'default',1e-5); -solver = struct('name','solver','class','char','isRequired',false,'default','Jacobi','options',{'Jacobi';'PCG';'GMRES';'Direct';'Linfactor';'Inverse'}); -precond = struct('name','preconditioner','class','char','isRequired',false,'default',[]); +solver = struct('name','solver','class','string','isRequired',false,'default','Jacobi','validValues',{{'Jacobi';'PCG';'GMRES';'Direct';'Linfactor';'Inverse'}}); +precond = struct('name','preconditioner','class','string','isRequired',false,'default',[],'validValues',{{'ilu'}}); kspace = struct('name','k-space','class','double','isRequired',false,'default',20); -maxit = struct('name','maximum iterations','class','double','isRequired','false','default',1e4); +maxit = struct('name','maximum iterations','class','double','isRequired',false,'default',1e4); LINEAR_SOLVE.Children = []; -LINEAR_SOLVE.Variables = struct('relTol',relTol,'solver',solver,'precond',precond,'kspace',kspace,'maxit',maxit); +LINEAR_SOLVE.Variables = struct('title',blockTitle,'description',description,... + 'relTol',relTol,'solver',solver,... + 'precond',precond,'kspace',kspace,... + 'maxit',maxit); LINEAR_SOLVE.isRequired = true; %% +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); stepTime = struct('name','step time','class','double','isRequired',true); -maxTime = struct('name','max time control','class','char','isRequired',false,'default','Reynolds'); +maxTime = struct('name','max time control','class','string','isRequired',false,'default','Reynolds'); scale = struct('name','max time scale factor','class','double','isRequired',false,'default',0.01); TIME_CONTROL.Children = []; -TIME_CONTROL.Variables = struct('stepTime',stepTime,'maxTime',maxTime,'scale',scale); +TIME_CONTROL.Variables = struct('title',blockTitle,'description',description,... + 'stepTime',stepTime,'maxTime',maxTime,... + 'scale',scale); TIME_CONTROL.isRequired = true; %% +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); + SOLUTION_CONTROL.Children = struct('LINEAR_SOLVE',LINEAR_SOLVE,'TIME_CONTROL',TIME_CONTROL); -SOLUTION_CONTROL.Variables = []; +SOLUTION_CONTROL.Variables = struct('title',blockTitle,'description',description); SOLUTION_CONTROL.isRequired = true; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% -func = struct('name','function','class','char','isRequired',true,'options',{'constant';},'default',{'constant'}); +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); +func = struct('name','function','class','string','isRequired',true,'validValues',{'constant';},'default',{'constant'}); value = struct('name','value','class','double','isRequired',true); scale = struct('name','scale factor','class','double','isRequired',false,'default',1); REYNOLDS.Children = []; -REYNOLDS.Variables = struct('func',func,'value',value,'scale',scale); +REYNOLDS.Variables = struct('title',blockTitle,'description',description,... + 'func',func,'value',value,'scale',scale); REYNOLDS.isRequired = true; %% -func = struct('name','function','class','char','isRequired',true,'options',{'constant';},'default',{'constant'}); +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); +func = struct('name','function','class','string','isRequired',true,'validValues',{'constant';},'default',{'constant'}); value = struct('name','value','class','double','isRequired',true); scale = struct('name','scale factor','class','double','isRequired',false,'default',1); CIRCULATION.Children = []; -CIRCULATION.Variables = struct('func',func,'value',value,'scale',scale); +CIRCULATION.Variables = struct('title',blockTitle,'description',description,... + 'func',func,'value',value,'scale',scale); CIRCULATION.isRequired = true; %% +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); FLOW_DEFINITION.Children = struct('REYNOLDS',REYNOLDS,'CIRCULATION',CIRCULATION); -FLOW_DEFINITION.Variables = []; +FLOW_DEFINITION.Variables = struct('title',blockTitle,'description',description); FLOW_DEFINITION.isRequired = true; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% -outputName = struct('name','output filename','class','char','isRequired',true); -description = struct('name','description','class','char','isRequired',false); -activeStep = struct('name','active step','class',{'double';'char'},'isRequired',false,'default','all'); +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); +outputName = struct('name','output filename','class','string','isRequired',true); +activeStep = struct('name','active step','class',{'double';'string'},'isRequired',false,'default','all'); outInit = struct('name','output initial step','class','logical','isRequired',false,'default',true); outFin = struct('name','output final step','class','logical','isRequired',false,'default',true); tIncr = struct('name','time increment','class','double','isRequired',true); dBuffer = struct('name','buffer increments','class','double','isRequired',false,'default',100); -variable = struct('name','variable','class','char','isRequired',true,'options',{'OMEGA','PSI','pU','pV'}); +variable = struct('name','variable','class','string','isRequired',true,'options',{'OMEGA','PSI','pU','pV'}); iX = struct('name','iX','class','double','isRequired',true); iY = struct('name','iY','class','double','isRequired',true); RESULT.Children = []; -RESULT.Variables = struct('outputName',outputName,'description',description,... - 'activeStep',activeStep,'outInit',outInit,... - 'outFin',outFin,'tIncr',tIncr,'dBuffer',dBuffer,... - 'variable',variable,'iX',iX,'iY',iY); +RESULT.Variables = struct('title',blockTitle,'description',description,... + 'outputName',outputName,'activeStep',activeStep,... + 'outInit',outInit,'outFin',outFin,'tIncr',tIncr,... + 'dBuffer',dBuffer,'variable',variable,... + 'iX',iX,'iY',iY); RESULT.isRequired = false; %% -logName = struct('name','log filename','class','char','isRequired',false,'default',strcat('PFI_log_',datestr(now,'mm_dd_yyyy__HH:MM:SS'))); +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); +logName = struct('name','log filename','class','string','isRequired',false,'default',strcat('PFI_log_',datestr(now,'mm_dd_yyyy__HH:MM:SS'))); tIncr = struct('name','time increment','class','double','isRequired',false,'default',1e3); initStep = struct('name','initial step','class','logical','isRequired',false,'default',true); finStep = struct('name','final step','class','logical','isRequired',false,'default',true); logData = struct('name','log data','class','cell','isRequired',false,'default',{'Timestep';'Time';'Time Elapsed'}); LOG_INFO.Children = []; -LOG_INFO.Variables = struct('logName',logName,'tIncr',tIncr,... +LOG_INFO.Variables = struct('title',blockTitle,'description',description,... + 'logName',logName,'tIncr',tIncr,... 'initStep',initStep,'finStep',finStep,... 'logData',logData); LOG_INFO.isRequired = false; %% +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); plotFlow = struct('name','plotFlow','class','logical','isRequired',false,'default',false); plotState = struct('name','plotState','class','logical','isRequired',false,'default',false); saveFlow = struct('name','saveFlow','class','logical','isRequired',false,'default',false); saveState = struct('name','saveState','class','logical','isRequired',false,'default',false); IN_SITU.Children = []; -IN_SITU.Variables = struct('plotFlow',plotFlow,'plotState',plotState,'saveFlow',saveFlow,'saveState',saveState); +IN_SITU.Variables = struct('title',blockTitle,'description',description,... + 'plotFlow',plotFlow,'plotState',plotState,... + 'saveFlow',saveFlow,'saveState',saveState); IN_SITU.isRequired = false; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% -stepName = struct('name','title','class','char','isRequired',false); +blockTitle = struct('name','title','class','string','isRequired',false); +description = struct('name','description','class','string','isRequired',false); STEP.Children = struct('SOLUTION_CONTROL',SOLUTION_CONTROL,... 'FLOW_DEFINITION',FLOW_DEFINITION,... 'RESULT',RESULT,'LOG_INFO',LOG_INFO,... 'IN_SITU',IN_SITU); -STEP.Variables = struct('stepName',stepName); +STEP.Variables = struct('title',blockTitle,'description',description); STEP.isRequired = false; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% -PARAM.Children = struct('INFORMATION',INFORMATION,'GEOMETRY_DEFINITION',GEOMETRY_DEFINITION,'STEP',STEP); -PARAM.Variables = []; \ No newline at end of file +PFI.Children = struct('INFORMATION',INFORMATION,'INITIAL_GEOMETRY_DEFINITION',INITIAL_GEOMETRY_DEFINITION,'STEP',STEP); +PFI.Variables = []; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +nodeNames = { 'PFI'; ... + 'INFORMATION';... + 'INITIAL_GEOMETRY_DEFINITION';... + 'STEP';... + 'SOLUTION_CONTROL';... + 'LINEAR_SOLVE';... + 'TIME_CONTROL';... + 'FLOW_DEFINITION';... + 'REYNOLDS';... + 'CIRCULATION';... + 'RESULT';... + 'LOG_INFO';... + 'IN_SITU'}; + +nodeProperties = { rmfield(PFI,'Children');... + rmfield(INFORMATION,'Children');... + rmfield(INITIAL_GEOMETRY_DEFINITION,'Children');... + rmfield(STEP,'Children');... + rmfield(SOLUTION_CONTROL,'Children');... + rmfield(LINEAR_SOLVE,'Children');... + rmfield(TIME_CONTROL,'Children');... + rmfield(FLOW_DEFINITION,'Children');... + rmfield(REYNOLDS,'Children');... + rmfield(CIRCULATION,'Children');... + rmfield(RESULT,'Children');... + rmfield(LOG_INFO,'Children');... + rmfield(IN_SITU,'Children')}; + + +ParentChild = [ ... + 2 1; + 3 1; + 4 1;... + 5 4;... + 6 5;... + 7 5;... + 8 4;... + 9 8;... + 10 8;... + 11 4;... + 12 4;... + 13 4;]; + +nodeTable = table(nodeNames,nodeProperties,'VariableNames',{'Name','SectionProperties'}); +edgeTable = table([ParentChild(:,2) ParentChild(:,1)],'VariableNames',{'EndNodes'}); +pGraph = digraph(edgeTable,nodeTable); +plot(pGraph) \ No newline at end of file diff --git a/src/myInput.in b/src/myInput.in index 5924dd7..d1b4998 100644 --- a/src/myInput.in +++ b/src/myInput.in @@ -1,6 +1,6 @@ BEGIN PFI BEGIN INFORMATION - title = "DIRECT NUMERICAL SIMULATION OF PARABOLA FLOW via LINEAR SYSTEM OF EQUATIONS" + title = DIRECT NUMERICAL SIMULATION OF PARABOLA FLOW via LINEAR SYSTEM OF EQUATIONS END INFORMATION BEGIN INITIAL_GEOMETRY_DEFINITION @@ -17,7 +17,7 @@ BEGIN PFI BEGIN SOLUTION_CONTROL BEGIN LINEAR_SOLVE relative tolerance = 1e-5 - solver = krylov + solver = pcg END LINEAR_SOLVE BEGIN TIME_CONTROL @@ -43,7 +43,7 @@ BEGIN PFI BEGIN RESULT name = SurfaceVelocity - description = "Velocity History Along Parabola Surface" + description = Velocity History Along Parabola Surface active step = 1 output initial step = true output final step = true @@ -56,7 +56,7 @@ BEGIN PFI BEGIN RESULT name = U-VelocityProfile - description = "U-Velocity Profile History at Parabola Center Parabola Surface" + description = U-Velocity Profile History at Parabola Center Parabola Surface active step = 1 output initial step = true output final step = true @@ -69,7 +69,7 @@ BEGIN PFI BEGIN RESULT name = V-VelocityProfile - description = "V-Velocity Profile History at Parabola Center Parabola Surface" + description = V-Velocity Profile History at Parabola Center Parabola Surface active step = 1 output initial step = true output final step = true diff --git a/src/processInput.m b/src/processInput.m index 8805ba1..89c3e6a 100644 --- a/src/processInput.m +++ b/src/processInput.m @@ -1,9 +1,9 @@ -function [input,fLines] = processInput(inFile) +function [inGraph,fLines] = processInput(inFile) %% Read the text input file fLines = fileread(inFile); % Separate the file by individual lines -fLines = strip(strsplit(fLines,'\n')'); +fLines = string(strip(strsplit(fLines,'\n')')); %% Convert each line to UPPERCASE % Compatibility between 2016a and 2016b @@ -47,7 +47,7 @@ for ii = 1:length(dNames) fDuplicates = find(strcmpi([sType.Name],dNames(ii))); for jj = 1:length(fDuplicates) - sType(fDuplicates(jj)).Name = dNames(ii) + "_" + num2str(jj); + sType(fDuplicates(jj)).Name = dNames(ii) + "-" + num2str(jj); end end @@ -77,9 +77,9 @@ if ~isempty(SectionLines) for p = 1:length(SectionLines) - fvp = strsplit(SectionLines{p},"="); - sType(ii).field(p) = fvp(1); - sType(ii).value(p) = fvp(2); + fvp = string(strsplit(SectionLines{p},"=")); + sType(ii).field(p) = strip(fvp(1)); + sType(ii).value(p) = strip(fvp(2)); end end end @@ -88,8 +88,8 @@ % Define NodeTable for ii = 1:length(sType) nodeName{ii,1} = char(sType(ii).Name); - nodeFields{ii,1} = sType(ii).field'; - nodeValues{ii,1} = sType(ii).value'; + FVP{ii,1}.Names = sType(ii).field'; + FVP{ii,1}.Values = sType(ii).value'; end % Define Edges eCount = 0; @@ -106,7 +106,12 @@ end end EdgeTable = table(edgeNodes,'VariableNames',{'EndNodes'}); -NodeTable = table(nodeName,nodeFields,nodeValues,'VariableNames',{'Name','Field','Value'}); +NodeTable = table(nodeName,FVP,'VariableNames',{'Name','Parameters'}); inGraph = digraph(EdgeTable,NodeTable); plot(inGraph) + + +%% Verify input parameters +inGraph = verifyInput(inGraph); + end \ No newline at end of file diff --git a/src/verifyInput.m b/src/verifyInput.m new file mode 100644 index 0000000..847aa69 --- /dev/null +++ b/src/verifyInput.m @@ -0,0 +1,481 @@ +function inGraph = verifyInput(inGraph) +%% Get list of legal parameters +pfiGraph = generateLegalParameters; + +%% Verify PFI Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'PFI'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'PFI')); + +if (isUsed == false) + error('"PFI" block is required'); +end + +%% Verify INFORMATION Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'INFORMATION'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'INFORMATION')); + +if (isRequired == true) && (isUsed == false) + error('"INFORMATION" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'INFORMATION'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + end +end + +%% Verify INITIAL_GEOMETRY_DEFINITION Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'INITIAL_GEOMETRY_DEFINITION'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'INITIAL_GEOMETRY_DEFINITION')); + +if (isRequired == true) && (isUsed == false) + error('"INITIAL_GEOMETRY_DEFINITION" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'INITIAL_GEOMETRY_DEFINITION'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'nx') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'ny') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'xmin') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'xmax') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'ymin') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'ymax') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + end +end + +%% Verify STEP Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'STEP'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'STEP')); + +if (isRequired == true) && (isUsed == false) + error('"STEP" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'STEP'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + end +end + +%% Verify SOLUTION_CONTROL Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'SOLUTION_CONTROL'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'SOLUTION_CONTROL')); + +if (isRequired == true) && (isUsed == false) + error('"SOLUTION_CONTROL" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'SOLUTION_CONTROL'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + end +end + +%% Verify LINEAR_SOLVE Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'LINEAR_SOLVE'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'LINEAR_SOLVE')); + +if (isRequired == true) && (isUsed == false) + error('"LINEAR_SOLVE" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'LINEAR_SOLVE'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'relative tolerance') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'solver') + assert(any(strcmpi(pParam.solver.validValues,iParam.Values(ii)))) + elseif strcmpi(iParam.Names(ii),'preconditioner') + assert(any(strcmpi(pParam.precond.validValues,iParam.Values(ii)))) + elseif strcmpi(iParam.Names(ii),'k-space') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'maximum iterations') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + end +end + +%% Verify TIME_CONTROL Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'TIME_CONTROL'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'TIME_CONTROL')); + +if (isRequired == true) && (isUsed == false) + error('"TIME_CONTROL" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'TIME_CONTROL'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'step time') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'max time control') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'max time scale factor') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + end +end + +%% Verify FLOW_DEFINITION Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'FLOW_DEFINITION'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'FLOW_DEFINITION')); + +if (isRequired == true) && (isUsed == false) + error('"FLOW_DEFINITION" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'FLOW_DEFINITION'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + end +end + +%% Verify REYNOLDS Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'REYNOLDS'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'REYNOLDS')); + +if (isRequired == true) && (isUsed == false) + error('"REYNOLDS" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'REYNOLDS'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'function') + assert(any(strcmpi(pParam.precond.validValues,iParam.Values(ii)))) + elseif strcmpi(iParam.Names(ii),'value') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'scale') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + end +end + +%% Verify CIRCULATION Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'CIRCULATION'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'CIRCULATION')); + +if (isRequired == true) && (isUsed == false) + error('"CIRCULATION" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'CIRCULATION'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'function') + assert(any(strcmpi(pParam.precond.validValues,iParam.Values(ii)))) + elseif strcmpi(iParam.Names(ii),'value') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'scale') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + end +end + +%% Verify RESULT Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'RESULT'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'RESULT')); + +if (isRequired == true) && (isUsed == false) + error('"RESULT" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'RESULT'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'output filename') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'active step') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'output initial step') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'output final step') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'time increment') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'buffer increments') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'variable') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'iX') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'iY') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + end +end + +%% Verify LOG_INFO Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'LOG_INFO'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'LOG_INFO')); + +if (isRequired == true) && (isUsed == false) + error('"LOG_INFO" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'LOG_INFO'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'log filename') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'time increment') + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2double(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'initial step') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'final step') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'log data') + assert(isstring(iParam.Values(ii))) + end +end + +%% Verify IN_SITU Block +pRow = strcmpi(pfiGraph.Nodes{:,'Name'},'IN_SITU'); +pParam = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.Variables; +isRequired = pfiGraph.Nodes{pRow,'SectionProperties'}{1}.isRequired; +isUsed = any(strcmpi(inGraph.Nodes{:,'Name'},'IN_SITU')); + +if (isRequired == true) && (isUsed == false) + error('"IN_SITU" block is required'); +else + iRow = strcmpi(inGraph.Nodes{:,'Name'},'IN_SITU'); + iParam = inGraph.Nodes{iRow,'Parameters'}{1}; +end + +pFieldnames = string(fieldnames(pParam)); +for ii = 1:length(iParam.Names) + ipMatch = false(size(pFieldnames)); + for jj = 1:length(pFieldnames) + ipMatch(jj) = strcmpi(iParam.Names(ii), pParam.(pFieldnames{jj}).name); + end + + if any(ipMatch) == false + error(['"' iParam.Names(ii) '" not a valid command']) + end + + inGraph.Nodes{iRow,'Parameters'}{1}.Fields(ii,1) = string(pFieldnames{ipMatch}); + if strcmpi(iParam.Names(ii),'title') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'description') + assert(isstring(iParam.Values(ii))) + elseif strcmpi(iParam.Names(ii),'plotFlow') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'plotState') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'saveFlow') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + elseif strcmpi(iParam.Names(ii),'saveState') + assert(any(strcmpi({"true","false"},iParam.Values(ii)))) + inGraph.Nodes{iRow,'Parameters'}{1}.Values(ii) = str2num(iParam.Values(ii)); + + end +end