Matlab: Nested PDEG functions

1 visualizzazione (ultimi 30 giorni)
Soheil  Esmaeilzadeh
Soheil Esmaeilzadeh il 26 Mag 2016
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

Risposta accettata

Stephen23
Stephen23 il 2 Giu 2016
Modificato: Stephen23 il 2 Giu 2016
@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:

Più risposte (1)

Geoff Hayes
Geoff Hayes il 27 Mag 2016
Modificato: Stephen23 il 27 Mag 2016
Soheil - you have posted more code than you should have to your question. As such, that is likely to discourage people from attempting to answer it. I think even those on StackOverflow (given the link above) have indicated the same. In the future, post only relevant code and only enough that is necessary to reproduce the problem.
That being said, look at how you call cardiod1 from your main function:
function [ X ] = faces( d,hc )
cardioid1;
function [x,y,xt,yt,th] = cardioid1(bs,s)
% cardioid1 body
end
% other stuff
end
You are calling cardiod1 but not saving/storing any of the output parameters, one of which is your xt. So when the code in the other stuff section tries to access xt you get the expected error of undefined function or variable 'xt'. Since you are trying to make use of this output parameter, then you should change the above to
function [ X ] = faces( d,hc )
[x,y,xt,yt,th] = cardioid1;
function [x,y,xt,yt,th] = cardioid1(bs,s)
% body of caridioid1
end
% other stuff
end
so that you can get to all output parameters of the function.
I think that you have misunderstood the idea of nested functions. If function B is nested within function A, then B has access to the local variables of A. This doesn't work in the other direction which is what you are attempting (to have the local variables of the nested cardioid1 function be accessible to the "parent" faces function).
  4 Commenti
Soheil  Esmaeilzadeh
Soheil Esmaeilzadeh il 1 Giu 2016
And also if you have a look at here you will see function below:
function main2
nestfun2
function nestfun2
x = 5;
end
x = x + 1
end
But for me does not work as well!!!
Geoff Hayes
Geoff Hayes il 2 Giu 2016
For your last comment, you need to clarify what you mean by but for me does not work as well. What is happening? What are you expecting to happen?
As for the error message that indicates
"Output argument "y" (and maybe others) not assigned during call to "cardioid1""
look at your function signature
function [x,y,xt,yt,th] = cardioid1(bs,s)
If you exit this function before the x, y, xt, yt, and th have been defined, then you will observe this error message. (This may be due to the return that you have.) What you can do is just assign each a default value - whether this is zero or an empty matrix is entirely up to you. For example,
function [x,y,xt,yt,th] = cardioid1(bs,s)
x = [];
y = [];
xt = [];
yt = [];
theta = [];
% now follow with your code for this function

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by