MATLAB: Matlab: Nested PDEG functions

functionMATLABmatlab function

I have originally two functions as below: The first one:
function [ X ] = faces( d,hc )
[p,e,t] = initmesh(@cardioid1,'init','off');
load('func_contents.mat');
zval_u=-hc;
zval_d=-hc-d;
t(4,:)=t(1,:);
val(:,:)=p(:,t(:,:));
valu(:,:)=val(:,:);
valu(3,:)=zval_u;
vald(:,:)=val(:,:);
vald(3,:)=zval_d;
%%%%%%%%Upper face %%%%%%%%%%%%

for i=1:size(t,2)
% for i=1:3

X(1,i,:,:)=[valu(:,4*i-3)';valu(:,4*i-2)';valu(:,4*i-1)';valu(:,4*i)'];
end
bord1(1,:)=xt(1,:);
bord1(2,:)=yt(1,:);
end
And the second one as below:
function [x,y,xt,yt,th] = cardioid1(bs,s)
%CARDIOID1 Geometry File defining the geometry of a cardioid.

global r0 a1;
r0=1;
a1=1;
if nargin == 0
x = 12; % four segments in boundary

return
end
if nargin == 1
dl = [0 pi/6 2*pi/6 3*pi/6 4*pi/6 5*pi/6 6*pi/6 7*pi/6 8*pi/6 9*pi/6 10*pi/6 11*pi/6
pi/6 2*pi/6 3*pi/6 4*pi/6 5*pi/6 6*pi/6 7*pi/6 8*pi/6 9*pi/6 10*pi/6 11*pi/6 12*pi/6
1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0];
x = dl(:,bs);
return
end
x = zeros(size(s));
y = zeros(size(s));
if numel(bs) == 1 % bs might need scalar expansion

bs = bs*ones(size(s)); % expand bs

end
nth =190; % fine polygon, 100 segments per quadrant

r0=1;
th = linspace(0,2*pi,nth); % parametrization

r=r0+a1*cos(th);
xt = r.*cos(th); % Points for interpolation of arc lengths

yt = r.*sin(th)+1000;
% Compute parameters corresponding to the arc length values in s

th = pdearcl(th,[xt;yt],s,0,2*pi); % th contains the parameters

% Now compute x and y for the parameters th

r=r0+a1*cos(th);
x(:) = r.*cos(th);
y(:) = r.*sin(th)+1000;
save('func_contents.mat','-v6')
end
Inside the "faces" function I access the second function by @cardioid1 and when cardioid1 runs I pass its parameters to "faces" by saving of the workspace and loading it inside "faces" again.
Since I want to change this format to parallel, they mix up the names, since all will save under a single name.mat in a single directory.
Now I thought to make it nested function, so that each parallel process locally and directly have access to parameters of cardioid1.
So I changed it to below code:
function [ X ] = faces2( d,hc )
cardioid1;
function [x,y,xt,yt,th] = cardioid1(bs,s)
%CARDIOID1 Geometry File defining the geometry of a cardioid.
global r0 a1;
a1=0.1;
a2=0.1;
a3=0.5;
if nargin == 0
x = 12; % four segments in boundary
return
end
if nargin == 1
dl = [0 pi/6 2*pi/6 3*pi/6 4*pi/6 5*pi/6 6*pi/6 7*pi/6 8*pi/6 9*pi/6 10*pi/6 11*pi/6
pi/6 2*pi/6 3*pi/6 4*pi/6 5*pi/6 6*pi/6 7*pi/6 8*pi/6 9*pi/6 10*pi/6 11*pi/6 12*pi/6
1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0];
x = dl(:,bs);
return
end
x = zeros(size(s));
y = zeros(size(s));
if numel(bs) == 1 % bs might need scalar expansion
bs = bs*ones(size(s)); % expand bs
end
nth =190; % fine polygon, 100 segments per quadrant
r0=1;
th = linspace(0,2*pi,nth); % parametrization
r=r0+a1*cos(th);
xt = r.*cos(th); % Points for interpolation of arc lengths
yt = r.*sin(th)+1000;
% Compute parameters corresponding to the arc length values in s
th = pdearcl(th,[xt;yt],s,0,2*pi); % th contains the parameters
% Now compute x and y for the parameters th
r=r0+a1*cos(th);
x(:) = r.*cos(th);
y(:) = r.*sin(th)+1000;
% save('func_contents.mat','xt','yt')
end
[p,e,t] = initmesh(@cardioid1,'init','off');
pdemesh(p,e,t)
% load('func_contents.mat');
zval_u=-hc;
zval_d=-hc-d;
t(4,:)=t(1,:);
val(:,:)=p(:,t(:,:));
valu(:,:)=val(:,:);
valu(3,:)=zval_u;
vald(:,:)=val(:,:);
vald(3,:)=zval_d;
%%%%%%%%Upper face %%%%%%%%%%%%
for i=1:size(t,2)
% for i=1:3
X(1,i,:,:)=[valu(:,4*i-3)';valu(:,4*i-2)';valu(:,4*i-1)';valu(:,4*i)'];
end
bord1(1,:)=xt(1,:);
bord1(2,:)=yt(1,:);
end
But I get the error: Undefined function or variable 'xt'. Error in faces (line 71) bord1(1,:)=xt(1,:);
My question as well has an open thread in here

Best Answer

@Soheil Smz: what do you expect to happen? You have two possible solutions:
  1. Define the variable at the start of the parent function, which can then be accessed by the nested function.
  2. Use output arguments, exactly as Geoff Hayes advised you to do.
Geoff Hayes told you to use output augments, but I can't see any in your code:
function main2
nestfun2
function nestfun2
x = 5;
end
x = x + 1
end
When I fix your code following Geoff Hayes' advice exactly, it works perfectly:
function y = main2
y = nestfun2;
function x = nestfun2
x = 5;
end
y = y + 1
end
And tested:
>> main2
ans = 6
Or alternatively without output argument, but defining the variables at the start of the parent function:
function y = main3
y = 0;
nestfun2
function nestfun2
y = 5;
end
y = y + 1;
end
And tested:
>> main3
ans = 6
Both of these are explained very well in the documentation, here is the salient info "All of the variables in nested functions or the functions that contain them must be explicitly defined. That is, you cannot call a function or script that assigns values to variables unless those variables already exist in the function workspace."
There is more to read and learn:
Related Question