SDT-base         Contents     Functions         Previous Next     PDF Index

7.17  Variable names and programming rules (syntax)

The following rules are used in programming SDT and OpenFEM as it makes reading the source code easier.

All SDT functions are segmented and tagged so that the function structure is clearly identified. Its tree structure can be displayed and browsable through the sdtweb _taglist interface. You should produce code compatible with this browser including tags (string beginning by # in a comment), in particular at each command of your function.

In addition, input parsing section 7.17.4  section 7.17.5 and some utilities for directory handling section 7.17.6, post-treatment display section 7.17.6 and figure formatting/capturing section 7.17.6 have been standardized.

7.17.1  Variable naming conventions

Standardized variable names are


cargindex of current argument. For functions with variable number of inputs, one seeks the next argument with NewArg=varargin{carg};carg=carg+1;
CAM, Camstring command to be interpreted. Cam is the lower case version of CAM. Input parsing conventions are described in ParamEdit and urnPar.
j1,j2,j3 ...loop indices.
jGroup,jElt,jWindices for element groups, elements, integration points. For code samples use help('getegroup')
jParindices for experiments,see fe_range.
i,junit imaginary √−1. i,j should never be used as indices to avoid any problem overloading their default value.
i1,i2,i3 ...integer values intermediate variables
r1,r2,r3 ...real valued variables or structures
ind,in2,in3 ...vectors of indices, cind is used to store the complement of ind when applicable.
out,out1,out2 ...output variables.

The following names are also used throughout the toolbox functions


model, mo1, mo2 ...SDT model structures.
node,FEnode, n1, n2 ...nodes, FEnode is reserved as a global variable.
elt, FEelt, el1, el2 ...elements, FEelt is reserved as a global variable.
EGroup, nGroupstarting index of each group and number of groups in an element structure, see help('getegroup').
cEGIindex of elements for a given group in an element structure, see help('getegroup').
NNodereindexing vector, verifies NodeInd=NNode(NodeId). Can be built using NNode=sparse(node(:,1),1,1:size(node,1)).
ndreindexing object for DOF, verifies DofPos=feval(nd.getPosFcn,nd,DOF). Is built using nd=feval(fe_mknl('@getPosFromNd'),[],DOF);
RunOptrun options, a structure used to store options that are used in a command. RO can also be used.
adofcurrent active DOF vector.
cfpointer to a feplot figure.
gf, uf, ga, ua, go, uorespectively handle and userdata to a figure, handle and userdata to an axis, handle and userdata to a graphics subobject.
gc, evtrespectively active object and associated event in Java triggered callbacks.

7.17.2  GetData: model input parsing and dereference object copies

SDT uses objects to store multiple types of data. It is however sometimes required to generate a local derefrenced copy. The main example is to generate a model variant from the one stored in feplot without impacting the latter one. To avoid multiple object testing in the code, method sdth.GetData performs an efficient generic recovery if needed.

The following calls are supported

Sample calls are thus the following


cf=feplot;
model=cf.mdl;

% Generic recovery for all objects
mo1=sdth.GetData(model)

% Specific model recovery
[mo1,cg,mo2]=sdth.GetData(cf,'-mdl');
[mo1,cg,mo2]=sdth.GetData(cf.mdl,'-mdl');
[mo1,cg,mo2]=sdth.GetData(cf.mdl.GetData,'-mdl');

% Model recovery from nmap
% CurModel storage
model=struct('Node',[1 0 0 0 0 0 0],'Elt',feutil('addelt',[],'mass1',1));
RT=struct('nmap',vhandle.nmap);
RT.nmap('CurModel')=model;

% recover model
[mo1,RT]=sdth.GetData(RT,'-mdl');
% direct alternative from nmap
[mo1,nmap]=sdth.GetData(RT.nmap,'-mdl');


% Restraint to specific classes
r1=pmat(ones(1));
r2=sdth.GetData(r1); % generic call
r3=sdth.GetData(r1,'pmat'); % restrict to pmat
r3=sdth.GetData(r1,'pmat','omat'); % allow pmat or omat
r3=sdth.GetData(r1,'omat'); % restrict on omat: no effect on pmat

7.17.3  Coding style

The coding styles convention are detailed in the example below.

function [out,out1,out2,out3]=my_func(varargin); 

% Here you should place your help
% SDT functions always use varargin for input and [out,out1, ...] for
% output. 

% ask MATLAB to avoid some warnings the in the editor MLint
%#ok<*NASGU,*ASGLU,*CTCH,*TRYNC,*NOSEM>

% Get the command in varargin{1} and strip front/end blanks with comstr
% CAM is as input, Cam is lower case.
if nargin<1; CAM=''; Cam='';carg=1;
else;[CAM,Cam]=comstr(varargin{1},1); carg=2;
end


%% #Top : main level command Top  ------------------------------
%  the %% is to use Matlab cell, while #Top is a sdtweb _taglist tag
%  by default tags are set to level 1
% Now test that Cam starts by 'top' and then strip 3 characters and trim (+1)
if comstr(Cam,'top');[CAM,Cam]=comstr(CAM,4);

 if comstr(Cam,'manual');[CAM,Cam]=comstr(CAM,7);
 %% #TopLevel2 : subcommand level 2 - - - - - - - - - -2
 % - - - tells sdtweb this is a level 2 tag 
 % ending the line with -2 is sufficient in practice
 % any other level can be used by adding a higher number at the end of the tag line

  % recover other inputs
  r1=varargin{carg}; carg=carg+1; % get input and increment counter
  % get optionnal input arguments
  if carg<=nargin; r2=carargin{carg}; carg=carg+1; else; r2=[]; end
  % For more complex input arguments with many run options, 
  % use instead the input parsing conventions (see sdtweb syntax#syntInp)

 %% #TopEnd -2
 else; error('Top%s unknown',CAM);
 end
%% #End : typical commands placed at end of function
elseif comstr(Cam,'@');out=eval(CAM);
elseif comstr(Cam,'cvs')
 out='$Revision: 1.33 $  $Date: 2024/06/22 16:43:02 $';
else; error('my_func %s unknown',CAM);
end

%% #SubFunc : indicates start of subfunctions to taglist parsing
%% #my_sub_fun - - ------------------------------------------
function out=my_sub_fun(varargin)


7.17.4  Input parsing conventions, ParamEdit

Passing command options is a critical feature to enable little behavior alteration as function of the user needs although most of the functionality is the same. This allows in particular limiting code duplication.

From the input CAM variable, command option parsing utilities have been defined and standardized. See also the alternate urnPar format and the CinCell structure which describes possible extensions. The goal is to build a run option structure from the input command string while keeping the possibility to provide it as an extra argument.

The command parsing code is then

% Usual run options handling
% first possible to recover in extra input
if carg>nargin||~isstruct(varargin{carg});RO=struct;
else;RO=varargin{carg};carg=carg+1;
end
% Then parse CAM for command options,
% and assign default values to unspecified options
% values declared prior to the paramedit call are not overriden
[RO,st,CAM]=cingui('paramedit -DoClean',[ ...
 'param(val#%g#"Description")' ...
 'token(#3#"token modes does...")' ...
 '-parS("string"#%s#"parS modes available...")' ...
 ],{RO,CAM}); Cam=lower(CAM);
% If default parameters are more complex (arry, cell, ...)
% Use the following syntax which add only missing fields 
% as default to the provided structure
RO=sdth.sfield('AddMissing',RO,struct(...
'param2',linspace(1,100,3000),...  % Default param2 vector
'param3',{{'fixdof','proid 1'}}));  % Default param3 cell ...

The paramEdit call from cingui performs standard operations for each token in the second input string of the command. Each token follows the format token(val#fmt#"info"), and will generate a case sensitive field token in the structure RO. val is a default value that is applied if the field token is missing before the call. info is a string providing information on the token effect. fmt tells the type of input that should be parsed after the token, with the following rules:

Advanced usage may require nested string tokens, i.e. a string token that will itself contain a token list for a subcommand. The base parsing strategy is rather robust to these cases, but nested string matching patterns may sometimes be tricky. In such case, one should use nested double quotes for the inside string. E.g. 'command-token"subcommand -subtok' ' "subval" ' '"'. With such input, the subtoken will be correctly handled.

RO=struct;
CAM='comm-tok"subcomm -subtok''"''subval''"''"';
[RO,st,CAM]=cingui('paramedit -DoClean',[ ...
'tok(#%s#"token value with nested string")' ...
 ],{RO,CAM}); Cam=lower(CAM);
RO.tok % contains the full substring
% then in the sub command
[RB,st,CAM1]=cingui('paramedit -DoClean',[ ...
'subtok(#%s#" subtoken value with nested string")' ...
 ],{struct,RO.tok}); Cam1=lower(CAM1);
RB.subtok % contains the proper value

The output CAM has been stripped from any parsed data.

The format -token(val#fmt#"info") will require the presence of -token in the command to generate the token field in RO.

By convention, to handle interference between the extra input argument RO and default values overriding, any field present in RO prior to calling paramEdit will be left unchanged by the command.

7.17.5  Input parsing conventions, urnPar

Following the uniform resource name urn developments, commands are gradually changed from the ParamEdit to the parsing strategy implemented in sdtm.urnPar, where commands are of the form commandName{arg1,arg2}. See also the CinCell structure which describes possible extensions for GUI, ToolTip, ...

Example :

fmt='{freq%g,amplitude%g}{in%i,out%i,opt%31}';
CAM='CmdName{500,5.5,opt,in2}';
[CAM,RO]=sdtm.urnPar(CAM,fmt);

7.17.6  Commands associated to project application functions

The development of project application functions follow some must have such as project directory handling section 7.17.6, post-treatment handling section 7.17.6, image capture generation section 7.17.6. Some of these steps have been standardized over the years, which are documented in the present sections.

wd,fname

The files relative to a specific application are usually stored in a specific file tree. It is thus useful to access standard defined save directories in a robust manner, regardless of the operating system or the user. Standard applications developed by SDTools usually involve a user defined root directory from which the following subdirectories are defined

Each of these directories may contain any further tree to class data as desired.

To allow efficient recovery of a specific subdirectory or file in the final project file architecture, sdtweb provides commands in its utilities (see sdtweb Utils) that should be used by the main project function to search the project architecture subdirectories.

The wd command should package a search in its known subdirectories.

%% #wd -------------------------------------------------
elseif comstr(Cam,'wd')

if nargin==1 % output the possible root directories
 % assume this function is stored in root/m
 out=fileparts(which('my_func'));
 % possibly add specific root dirs outside the project
 % should be better handled with a preference
 wd2={'/p/my_files'}; % add as many as needed
 out=[out wd2];

else % get the subdirectory searched
 wd1=varargin{carg}; carg=carg+1;
 % get the project root directory (several ones admitted)
 wd0=my_func('wd');
 % find the subdirectory
 out=sdtweb('_wd',wd0,wd1);
end

The fname command should package a file search in the known subdirectories

%% #fname -----------------------------------------------
elseif comstr(Cam,'fname')
fname=varargin{carg}; carg=carg+1;
% get the available root directories
wd=my_func('wd');
% search for the file
out=sdtweb('_fname',fname,wd);

view

The generation of displayed post-treatments should be handled by a command named View, that will centralize the feplot manipulations required to generate ad hoc displays. Variations of display are handled in the command, first and second input should be the feplot pointer and optionally a deformation data.

A sample call to be handled by the view command could then be.

my_project('ViewUpStress',cf);

im

The generation of image captures from figures (feplot  iiplot or standard MATLAB figures) should be handled by a command named im, that will centralize formatting and saving. This command should

For details on figure formatting, see comgui objSet, for details on figure naming strategy see comgui ImFtitle, for low level image capturing calls, see comgui ImWrite.

A suggested layout for the im command of a sample my_func function is then

%% #im : figure formatting ---------------------------------------------------
elseif comstr(Cam,'im')
% sdt_table_generation('Rep{SmallWide}');comstr(ans,-30)

 if nargin==2 % generate the calling string
   pw0=pwd;
   if isfield(varargin{2},'ch') % multiple generation with imwrite ch
    RO=varargin{2};cf=feplot;
    % Create an possibly change to directory
    sdtkey('mkdircd',my_func('wd','plots',sscanf(cf.mdl.name,'%s',1)));
    RO.RelPath=1; % Save links with path relative to current position
    RO=iicom(cf,'imwrite',RO);
    fid=fopen('index.html','w');fprintf(fid,'%s',RO.Out{:});fclose(fid);
    cd(pw0); 
    
   elseif ~ischar(varargin{2}); % Apply reshaping to figure
     gf=varargin{2};if ~ishandle(gf);figure(gf);plot([0 1]);end
     cingui('objset',gf,my_func(CAM))
     % if feplot, center the display
     if strcmpi(get(gf,'tag'),'feplot');iimouse('resetvie');end    
    
   elseif strcmpi(varargin{2},'.') % if '.' get automatic naming
    st=sprintf('imwrite-objSet"@my_func(''%s'')"-ftitle',varargin{1});
    comgui(st);

   else
    cd(my_func('wd','plots'));
    st=sprintf('imwrite-objSet"@my_func(''%s'')"-ftitle%s',varargin{1:2});
    comgui(st);
    cd(pw0);
   end

 elseif comstr(Cam,'imw1') % Figure formatting options for w1
    out={'position',[NaN,NaN,450*[1.5 2]],'paperpositionmode','auto', ...   
        '@exclude',{'legend.*'},'@text',{'FontSize',14}, ...
        '@axes',{'FontSize',14,'box','on'}, ...
        '@ylabel',{'FontSize',14,'units','normalized'}, ...
        '@zlabel',{'FontSize',14,'units','normalized'}, ...
        '@title',{'FontSize',14}, ...
        '@line',{'linewidth',1}, ...
        '@xlabel',{'FontSize',14,'units','normalized'}};

% elseif ... use as many commands as needed

 else; error('%s unknown',CAM);
 end

This way, the following tasks can be easily performed

% Im calls for figure capturing
gf=figure(1); plot([1 0]);
% Capture an image from figure 1 with formatting w1 and named test.png
my_func('imw1','test.png');
% Capture an image from figure 1 with formatting w1 with an automatic name
my_func('imw1','.');
% Format figure 1 according to w1 options
my_func('imw1',gf);
% Get formatting options for w1
r1=my_func('imw1');

7.17.7  Commands associated to tutorials

In a training function or in any function where a tutorial could be executed, the syntax is the following

 elseif comstr(Cam,'tuto')
  %% #Tuto (implement standard behaviour of tuto command) -1
   % Execute the tutorial with CAM commands or open the tuto tree if empty CAM
  eval(sdtweb('_tuto',struct('file','current_function_name','CAM',CAM))); 
  if nargout==0; clear out; end
 elseif comstr(Cam,'tutoname')
  %% #TutoTutoname-2
  % See sdtweb('LinkToHTML') % Open the HTML corresponding to the tutorial
  
  %% Step 1 : Description of step1
  % See sdtweb('LinkToHTML') % Open HTML detailed doc related to this step
  
  %% Step 1.1 : Description of substep 1.1
  
  % Code to execute correponding to Step 1.1
   
  %% Step 1.2 : Description of substep 1.1
  
  % Code to execute correponding to Step 1.2
  
  % Step 2 : Description of step2
  % See sdtweb('LinkToHTML') % Open HTML detailed doc related to this step
 
  % Code to execute correponding to Step 2
 
  %% EndTuto
  
 elseif comstr(Cam,'tutoname2')
  %% #TutoTutoname2-2
  % See sdtweb('LinkToHTML') % Open the HTML corresponding to the tutorial
  
  %% EndTuto
  
% elseif ... use as many commands as needed

This way, the following commands are usually executed :

% Open the tree containing all the tutorial and clickable buttons
my_func('Tuto');
% Execute the whole tutorial (useful for test auto)
my_func('TutoTutoname');
% Execute a tutorial up to a given step (here section 2.3)
my_func('TutoTutoname -s2.3');

©1991-2024 by SDTools
Previous Up Next