jacob30
jacob30

Reputation: 151

Matlab Solve Symbolic Function after rearranging for new subject

I have this formula that I use to calculate Vo given Ps AND it can be re-arranged for Ps given Vo:

Vo=(Ps)*(BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd

I want to make a versatile function for this purpose in MATLAB. I start by declaring a symbolic function and solving it with numerical substitutions this way:

syms Ps BWc BWs Ro n LdB Rpd;
Vo(Ps,BWc,BWs,Ro,n,LdB,Rpd)=(Ps)*(BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd;
Vo(250,0.12,1000,0.01,4,0.5,75)

I want to be able to re-arrange the symbolic function for Ps and solve again:

 Ps(Vo,BWc,BWs,Ro,n,LdB,Rpd)= solve('Vo=(Ps)*(BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd','Ps');
 Ps(0.0063,0.12,1000,0.01,4,0.5,75)

However the above two lines do not work. I get the error for the last line above: "Operands to the || and && operators must be convertible to logical scalar values." I have also tried:

syms Vo Ps BWc BWs Ro n LdB Rpd;
Vo(Ps,BWc,BWs,Ro,n,LdB,Rpd)=(Ps)*(BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd;
Vo(250,0.12,1000,0.01,4,0.5,75)
Ps(Vo,BWc,BWs,Ro,n,LdB,Rpd)=(Vo)/((BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd);
Ps(0.0063,0.12,1000,0.01,4,0.5,75)

What is the correct way to use the symbolic toolbox for this purpose?

Upvotes: 0

Views: 640

Answers (1)

horchler
horchler

Reputation: 18484

The issue may be because you have a variable called Vo and you're also using Vo to define a function. You can't do that and still use both. It's effectively an issue of variable scope. Here's how you can successfully use solve:

syms Vo Ps BWc BWs Ro n LdB Rpd;
Vo_fun(Ps,BWc,BWs,Ro,n,LdB,Rpd) = Ps*(BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd
Vo_fun(250,0.12,1000,0.01,4,0.5,75)
Ps_fun(Vo,BWc,BWs,Ro,n,LdB,Rpd) = solve(Vo==Vo_fun,Ps)
Ps_fun(0.0063,0.12,1000,0.01,4,0.5,75)

I don't see the need to use symbolic math at all in this case. Simple anonymous functions would suffice, e.g.:

Vo = @(Ps,BWc,BWs,Ro,n,LdB,Rpd)(1/10^((LdB*(2*n + 3))/10)*BWc*Ps*Ro*Rpd)/BWs;
Ps = @(Vo,BWc,BWs,Ro,n,LdB,Rpd)(10^((LdB*(2*n + 3))/10)*BWs*Vo)/(BWc*Ro*Rpd);

Note that there is no problem with scope here in the naming of the functions. If the other arguments aren't changing, you can make these just a function of Vo and Ps:

BWc = ...
BWs = ...
Ro = ...
n = ...
LdB = ...
Rpd = ...
Vo = @(Ps)(1/10^((LdB*(2*n + 3))/10)*BWc*Ps*Ro*Rpd)/BWs;
Ps = @(Vo)(10^((LdB*(2*n + 3))/10)*BWs*Vo)/(BWc*Ro*Rpd);

Or you could create a single regular function that handles either input:

function out=VoPs(name,value,BWc,BWs,Ro,n,LdB,Rpd)
if (ischar(name) && strcmp(name,'Ps')) || (isa(name,'sym') && logical(name==sym('Ps')))
    Ps = value;
    Vo = Ps*(BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd;
elseif (ischar(name) && strcmp(name,'Vo')) || (isa(name,'sym') && logical(name==sym('Vo')))
    Vo = value;
    Ps = Vo/((BWc/BWs)*Ro*(10^((-(3+2*n)*LdB)/10))*Rpd);
else
    error('VoPs:InvalidName','Name input must be ''Vo'' or ''Ps''.')
end

Upvotes: 0

Related Questions