I am trying to solve a model of 4 equations, where everything is real. It is essentially a pipe branch problem with "1" being upstream of the pump (with some head on it), and "2" and "3" are downstream w/o head. The units are English.
Anyway, I'm just solving the system of 4 equations and 4 unknowns and looking at a plot of head (ha) vs. total flow rate (Q1). Across this space though I only am collecting points in a vertical line, i.e. the head changes but the flowrate doesn't.
I was thinking the problem may be some variables are being held onto, but I treat "ha" the same as "Q1" so that doesn't seem likely... Realistically, this is matching a system curve to a pump curve, and of course that point moves when the system changes (both flowrate and head), so it seems I am doing something wrong....
Here is the script:
clear sol1 sol2 sol3 sol4 S q h
clc; clearvars; close all;
syms Q1 Q2 Q3 ha
D1 = 1.25/12; Z1 = 0; P1 = 62.4*10; A1 = pi*(1/4)*D1*D1; f1 = 0.011; L1 = 50;
D2 = 0.5/12; Z2 = 25; P2 = 0; A2 = pi*(1/4)*D2*D2; f2 = 0.011; L2 = 100; %V2 = Q2 / A2;
D3 = 0.5/12; Z3 = 10; P3 = 0; A3 = pi*(1/4)*D3*D3; f3 = 0.011; L3 = 100; %V3 = Q3 / A3;
gamma = 62.468;
origPumpData = [0 150; 0.4 148; 0.8 145; 1.2 143; 1.6 141; 2 139; 2.4 138; 2.8 136; 3.2 134; 3.6 132; 4 130; 4.4 128; 4.8 127; 5.2 125; 5.6 124; 6 121; 6.4 118; 6.8 117; 7.2 115; 7.6 113; 8 111; 8.4 110; 8.8 108; 9.2 106; 9.6 104; 10 102; 10.4 100; 10.8 98; 11.2 97;
11.6 94; 12.0 93; 12.4 91; 12.8 89; 13.2 87; 13.6 86; 14 84; 14.4 82; 14.8 80; 15.2 78; 15.6 76; 16 74; 16.4 72; 16.6 70];
pumpData(:,1) = origPumpData(:,1)/448.8312;
pumpData(:,2) = origPumpData(:,2);
polyFit = fit(pumpData(:,1),pumpData(:,2),'poly2');
assume(in(Q1,'real') & Q1 > 0.0001 & Q1 < 1 );
assume(in(Q2,'real') & Q2 > 0.0001 & Q2 < 1 );
assume(in(Q3,'real') & Q3 > 0.0001 & Q3 < 1 ) ;
assume(in(ha,'real') & ha > 0.0001 & ha < 1000.0);
eq1 = #(Q1) polyFit.p1*Q1*Q1 + polyFit.p2*Q1 + polyFit.p3;
eq2 = #(P1,Z1,F1,Q1,A1,L1,D1,P2,Z2,F2,Q2,A2,L2,D2) P1/gamma + ((Q1/A1)^2)/64.4 + Z1 - hf(F1,L1,D1,Q1,A1) - hf(F2,L2,D2,Q2,A2) + ha == P2/gamma + ((Q2/A2)^2)/64.4 + Z2;
eq3 = #(P1,Z1,F1,Q1,A1,L1,D1,P3,Z3,F3,Q3,A3,L3,D3) P1/gamma + ((Q1/A1)^2)/64.4 + Z1 - hf(F1,L1,D1,Q1,A1) - hf(F3,L3,D3,Q3,A3) + ha == P3/gamma + ((Q3/A3)^2)/64.4 + Z3;
eq4 = Q1 == Q2 + Q3;
guesses = [0.07116936917086152675558661517184;
0.035125850031368916048762418970837;
0.036043519139492610706824196201003;
303.02361035523126099594683749354];
for i = 1:1:2
disp(i)
disp(Z1)
Z1 = Z1-5
f1 = f1+0.01
f3 = f3 + 0.01
S(i) = vpasolve([eq1(Q1) eq2(P1,Z1,f1,Q1,A1,L1,D1,P2,Z2,f2,Q2,A2,L2,D2) eq3(P1,Z1,f1,Q1,A1,L1,D1,P3,Z3,f3,Q3,A3,L3,D3) eq4], [Q1 Q2 Q3 ha], guesses )
S(i).Q1
S(i).Q2
S(i).Q3
S(i).ha
q(i) = S(i).Q1
h(i) = S(i).ha
guesses = [S(i).Q1 S(i).Q2 S(i).Q3 S(i).ha]'
clear S
end
plot( q, h, '*b');
function hf = hf(f,L,D,Q,A)
hf = f*(L/D)*(1/64.4)*(Q/A)^2;
end
you're solving eq1 == 0(default) and computing Q1, independent of other equations and parameters. that's why you get constant Q1 in every iteration.
Here is the code:
syms G1 G2 G3 M1 M2 M3 P1 P2 P3 D1 D2 D3
S = solve(0 == 0.9 * (20 - G1) - 0.012 * D3 * G1, ...
0 == 0.9 * (20 - G2) - 0.012 * D1 * G2, ...
0 == 0.9 * (20 - G3) - 0.012 * D2 * G3, ...
0 == -0.0033 * M1 + 0.002 * G1, ...
0 == -0.0033 * M2 + 0.002 * G2, ...
0 == -0.0033 * M3 + 0.002 * G3, ...
0 == 0.1 * M1 - 0.0033 * P1 + 2 * 0.5 * D1 - 2 * 0.025 * (P1 ^ 2), ...
0 == 0.1 * M2 - 0.0033 * P2 + 2 * 0.5 * D2 - 2 * 0.025 * (P2 ^ 2), ...
0 == 0.1 * M3 - 0.0033 * P3 + 2 * 0.5 * D3 - 2 * 0.025 * (P3 ^ 2), ...
0 == -0.5 * D1 + 0.025 * (P1 ^ 2) + 0.9 * (20 - G2) - 0.012 * D1 * G2, ...
0 == -0.5 * D2 + 0.025 * (P2 ^ 2) + 0.9 * (20 - G3) - 0.012 * D2 * G3, ...
0 == -0.5 * D3 + 0.025 * (P3 ^ 2) + 0.9 * (20 - G1) - 0.012 * D3 * G1)
The problem is that I need real solution, but I have got answers with roots. How can I get real answers?
Assuming by "real solution" you mean a numeric value instead of the exact root-of-polynomial form, there are two options depending on how you intend on using the results:
double: this will evaluate the RootOf expressions, assuming there are no free parameters, and return a numeric output of class double. While the output is now limited to double-precision, if your goal is to use the roots in computation and care about performance, this is the fastest option.
vpa: this will evaluate the RootOf expressions, assuming there are no free parameters, and return a Symbolic output of class sym. While the output is now able to be approximated to varying degrees of accuracy at evaluation by calling digits beforehand, there may be a large computational overhead in subsequent calculations due to its Symbolic nature.
I have a piece of code in matlab:
deg = 0:57;
theta = deg*pi/180;
N = 16;
lambda = 0.1;
dxy = 0.4*lambda;
nn = 1:N;
y = (nn - 0.5*(N+1))*dxy;
BB = [0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 0.63 0.57 0.29 0.23 0.20 0.17 0.15 0.14 0.12 0.11 0.10 0.10 0.09 0.09 0.08 0.08 0.07 0.07 0.07 0.06 0.06 0.06 0.06 0.00 0.00 0.00];
AA = exp(2*pi*1j/lambda*sin(theta')*y);
w = AA \ fliplr(BB)';
I want a least mean square solution to w for AA*w = BB' such that
the absolute values of elements of w equal to 1.
I'm trying to simulate nonlinear vehicle braking system with ode45.
I take a short time to learning MATLAB. then, I don't know why error occur.
It would be very appreciated if you could point out errors, and tell me how to solve.
code 1. main script
code 2. function
code 3. errors
clear;
global m f Jw rw Fz Cd p A bw fw Nw g uw seta Te Tb T p0
x = [0 0.025 0.05 0.1 0.125 0.15 0.175 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1]
y = [0 0.225 0.45 0.65 0.685 0.705 0.69 0.68 0.65 0.635 0.63 0.6275 0.625 0.6225 0.62 0.6175 0.615 0.6125 0.610 0.6075 0.6050 0.6 0.5975 0.5950]
%plot(x,y)
p0=polyfit(x,y,6)
%y=polyval(p,x)
m = 1400; f = 0.01; Jw = 0.65; rw = 0.31; Fz = 3560.0; Cd = 0.5; p = 1.202; A = 1.95;
bw = 0.0; fw = 0.0; Nw = 4; g = 9.81; uw = 0.0; seta = 0.0; Te = 0.0; Tb = 1000.0; T = Te - Tb;
[t,i] = ode45(#dott,[0.0 1.0],[20 20]);
plot(t,i);
axis([0 1 0 20]);
legend('x1','x2');
function xdot = dott(t,x)
global m f Jw rw Fz Cd p A Nw Te Tb p0
X = [0 0.025 0.05 0.1 0.125 0.15 0.175 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1];
Y = [0 0.225 0.45 0.65 0.685 0.705 0.69 0.68 0.65 0.635 0.63 0.6275 0.625 0.6225 0.62 0.6175 0.615 0.6125 0.610 0.6075 0.6050 0.6 0.5975 0.5950];
%UNTITLED2 Summary of this function goes here
%Detailed explanation goes here
xdot = zeros(2,1);
Y=p0(1,1)*((x(2)-x(1))/x(1))^6+p0(1,2)*((x(2)-x(1))/x(1))^5+p0(1,3)*((x(2)-x(1))/x(1))^4+p0(1,4)*((x(2)-x(1))/x(1))^3+p0(1,5)*((x(2)-x(1))/x(1))^2+p0(1,6)*((x(2)-x(1))/x(1))^1+p0(1,1)*((x(2)-x(1))/x(1));
xdot(1)=(-0.5*p*Cd*A(x(2)/(1+Y)*rw)*(x(2)/(1+Y)*rw)-f*m+Nw*Y*Fz)/(rw*m);
xdot(2)=(Te-Tb-rw*Y*Fz)/Jw;
end
??? Subscript indices must either be real positive integers or logicals.
Error in ==> dott at 9
xdot(1)=(-0.5*p*Cd*A(x(2)/(1+Y)*rw)*(x(2)/(1+Y)*rw)-f*m+Nw*X*Fz)/(rw*m);
Error in ==> odearguments at 98
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ==> ode45 at 172
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs, odeFcn, ...
Error in ==> a at 14
[t,i] = ode45(#dott,[0.0 1.0],[20 20]);
I'm pretty sure your error is in this statement:
A(x(2)/(1+Y)*rw)
The way you write it, you're trying to use x(2)/(1+Y)*rw as an index to the scalar A. I guess you want to multiply is this way:
... A * (x(2) / (1 + Y) * rw) ...
To make the code more readable:
Use spaces. A long compact line is really hard to read.
Split long lines into several using three dots ...
Something like this is easier to read in my opinion:
Y = p0(1,1) * ((x(2) - x(1)) / x(1))^6 + p0(1,2) * ...
((x(2) - x(1)) / x(1))^5 + p0(1,3) * ((x(2) - x(1)) / x(1))^4 ...
+ p0(1,4) * ((x(2) - x(1)) / x(1))^3 + p0(1,5) * ((x(2) - x(1)) / ...
x(1))^2 + p0(1,6) * ((x(2) - x(1)) / x(1))^1 + p0(1,1) * ...
((x(2) - x(1)) / x(1));
clc;
clear all;
syms y a2 a3
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% [ 0.5 0.25 0.125 ] [ a2 ] [ y ]
% [ 1 1 1 ] [ a3 ] = [ 3 ]
% [ 2 4 8 ] [ 6 ] [ 2 ]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
M = [0.5 0.25 0.125; 1 1 1; 2 4 8];
t = [a2 a3 6];
r = [y 3 2];
sol = M * t'
s1 = solve(sol(1), a2) % solve for a2
s2 = solve(sol(2), a3) % solve for a3
This is what I have so far.
These are my output
sol =
conj(a2)/2 + conj(a3)/4 + 3/4
conj(a2) + conj(a3) + 6
2*conj(a2) + 4*conj(a3) + 48
s1 =
- conj(a3)/2 - 3/2 - Im(a3)*i
s2 =
- conj(a2) - 6 - 2*Im(a2)*i
sol looks like what we would have if we put them back into equation form:
0.5 * a2 + 0.25 * a3 + 0.125 * a4
a2 + a3 + a4 = 3
2*a2 + 4*a3 + 8*a4 = 2
where a4 is known == 6.
My problem is, I am stuck with how to use solve to actually solve these equations to get the values of a2 and a3.
s2 solve for a3 but it doesn't match what we have on paper (not quite).
a2 + a3 + 6 = 3 should yield a3 = -3 - a2.
because of the imaginary. Somehow I need to equate the vector solution sol to the values [y 3 2] for each row.
You need to provide solve function with an equation. Just as simple as that:
sol = solve(M * t' == r');
As a result you have
sol.a2 = 17
sol.a3 = -20
sol.y = 17/4
This works for MATLAB R2012b. In general this can be solved just in one line:
solve('a2 / 2 + a3 / 4 - y + 3 / 4 = 0', 'a2 + a3 + 3 = 0', '2 * a2 + 4 * a3 + 46 = 0')
P.S. I have checked, this works for MATLAB R2011b.