当退出fzero时,我看到这是函数f(x)的f值,我在用代码解决问题时打印出来。
"离开FZERO
fd_final = NaN "
这是导致问题的代码 " fval = colebrook(Re,Param.e_D); "
但是,如果使用此代码部分,则在退出fzero时没有问题。
%*******此代码有效************************************ ******
var1 = Param.e_D/3.7 + 2.51/Re/sqrt(fd);
fval = 1/sqrt(fd) + 2*log10(var1);
%*******此代码有效************************************ ******
" 甚至将函数colebrook的代码放入IF语句(而不是调用函数)中,使用它仍然会产生问题。
建议去哪看?
这是代码
% plot_dh_dt_tank_drain_v2.m
%
% This MATLAB m-file makes a plot of dh/dt vs. h
% for the tank draining problem, and plots the
% tank height as a function of time.
% K. Beers. MIT ChE. 9/19/02
function iflag_main = plot_dh_dt_tank_drain_v2();
iflag_main = 0;
% set problem parameters
Param.Dt = 0.566 ; % tank diameter in (m)
Param.At = pi*(Param.Dt/2)^2; % Tank area (m2)
Param.Ht = 1.245 ; % tank height equivalent (m)
Param.dh = 0.152 ; % elevation of tank from ref ()m
Param.water_H_init = 0.7 ; % initial tank water level (m)
p_max_tank = 2.9 ; % initial tank pressure (kg/cm2)
% initial tank pressure convert to (kg/sec*m2, N/m2)
Param.Press_init = p_max_tank/(1.02e-5) ;
% minimum tank water height in (m)
Param.Ht_water_min = Param.water_H_init*(1/2);
Param.Hout = 1.32 ; % faucet elevation from refrence (m)
Param.Dp = 0.0135 ; % pipe diameter (m)
Param.Ap = pi*(Param.Dp/2)^2; % pipe cross sectional area (m2)
% *********** Variable Parameter ******************
Param.L = 180 ; % total pipe length in (m)
Param.density = 1000 ; % water density in Kg/m^3
Param.viscosity = 1.03e-3 ; % water viscosity in Pa*s
% *********** Variable Parameter ******************
Param.e = 0.007e-3 ; % effective surface roughness of pipe (m)
Param.e_D = Param.e/Param.Dp ; % relative surface roughness
Param.g = 9.81 ; % gravity acceleration (m/s^2)
Param.K_L = 0.5 ; % entrance loss coefficient
Param.K_Elb = 0.5 ; % entrance loss coefficient
n_elbows = 7 ; % number of elbows
n_valves = 1 ; % number of valves
% 90° Elbow Curved, Threaded Standard Radius
% (R/D = 1) (L/D)eq = 30
Leq = n_elbows*30*Param.Dp;
Param.L = Param.L + Leq; % Equvalent pipe length
% Ball valve, standard, β = 1 (L/D)eq = 3
Leq = n_valves*3*Param.Dp;
Param.L = Param.L + Leq; % Equvalent pipe length
coef.a1 = (1/2)*Param.density*(Param.Ap/Param.At)^2 ;
coef.a2 = Param.density*Param.g ;
coef.a3 = (1/2)*Param.density ;
coef.a4 = Param.density*Param.g*Param.Hout ;
coef.a5 = (1/4)*Param.density ;
% coef.a6 = (1/(2*Param.density))*K_L_sum ;
% I am doing Equivalent Pipe length cal. instead
coef.a6 = 0;
coef.a7 = (Param.L/Param.Dp)*(1/2)*Param.density;
% Set initial water level in tank (m)
h_max = Param.water_H_init + Param.dh;
% set minimum water level (m)
h_min = Param.Ht_water_min + Param.dh;
% set interval in height values (m)
dh = 0.02;
% Set grid of tank height values
h_grid = [h_min : dh : h_max];
num_h = length(h_grid);
% Calculate tank volume delta (m2)
dvol = Param.At*dh;
% Calculate starting Air volume in tank in (m3)
Vol_Air_t = Param.At*(Param.Ht - Param.water_H_init) ;
% Allocate vector to store output values
dh_dt_grid = zeros(size(h_grid));
Q_grid = zeros(size(h_grid));
V_grid = zeros(size(h_grid));
Re_grid = zeros(size(h_grid));
fd_grid = zeros(size(h_grid));
p_tank = zeros(size(h_grid)); % Pressure of Air in Tank
% open a file for writing
fid = fopen('Bernoulli_Eq.txt', 'wt');
% fprintf(fid,' p_air + coef.a2*Param.h - coef.a4 coef.a3 + coef.a5 ...
% '+ coef.a6 + coef.a7*fd - coef.a1 V ' \n\n',);
c1 = ' p_air a1*V^2 a2*ht = a3*V^2 a4 a5*V^2';
c2 = ' a6*V^2 a7*fd*V^2 V f_D Re';
fprintf(fid,'%s %s \n\n',c1,c2 );
fclose(fid);
% Use initial guess of infinite Re limit
% for commercial steel pipe.
fd_guess = 0.02;
% Initial air cushion pressure
p_air = Param.Press_init;
% Call solver to compute results for each h value.
verbose = 0;
for k = num_h : -1 : 1
[dh_dt_grid(k),Q_grid(k),...
V_grid(k),Re_grid(k),fd_grid(k)] = ...
tank_drain(h_grid(k),fd_guess,Param,verbose,p_air,coef);
% store friction factor as guess for next
% iteration
fd_guess = fd_grid(k);
% Store tank air pressure
p_tank(k) = p_air;
% Calculate new air pressure for time step t+dt
p_air = p_air*Vol_Air_t/(Vol_Air_t + dvol);
% Calculate new air volume
Vol_Air_t = Vol_Air_t + dvol;
end
% Now, estimate times at which tank reaches each height
time = zeros(size(h_grid));
for k = (num_h-1) : -1 : 1
dt = (h_grid(k)-h_grid(k+1))/dh_dt_grid(k+1);
time(k) = time(k+1) + dt;
end
% open a file for writing
fid = fopen('1output_tank.txt', 'w');
kg_cm2 = 1.02*10^-5;
% Table Header
fprintf(fid, 'Time Height P_Air Q*10^4 V_pipe Re fd\n\n');
% print values in column order
for k = (num_h-1) : -1 : 1
fprintf(fid, '%6.2f %4.2f %6.0f %4.2f %4.2f %6.0f %6.4f\n\n',...
time(k),h_grid(k),p_tank(k),Q_grid(k)*10^4,V_grid(k),Re_grid(k),...
fd_grid(k));
end
fclose(fid);
% Make plots of results
figure;
% tank height rate of change
subplot(2,1,1);
plot(h_grid,dh_dt_grid);
xlabel('h (m)');
ylabel('dh/dt (m/s)');
% tank height vs. time
subplot(2,1,2);
plot(time,h_grid);
xlabel('t (s)');
ylabel('h (m)');
gtext('Tank draining problem');
% new figure for other results
figure;
% Velocity in drain pipe
subplot(2,2,1);
plot(h_grid,V_grid);
xlabel('h (m)');
ylabel('V (m/s)');
% volumetric flow rate
subplot(2,2,2);
plot(h_grid,Q_grid);
xlabel('h (m)');
ylabel('Q (m^3/s)');
% Reynolds' number in drain pipe
subplot(2,2,3);
semilogy(h_grid,Re_grid);
xlabel('h (m)');
ylabel('Re');
% friction factor
subplot(2,2,4);
plot(h_grid,fd_grid);
xlabel('h (m)');
ylabel('f_D');
gtext('Tank draining problem');
iflag_main = 1;
return;
% ==============================================
% tank_drain.m
%
% This MATLAB program calculates the velocity
% through the exit pipe for a tank-draining
% problem at a specified value of the height
% of water in the tank.
%
% K. Beers
% MIT ChE. 9/18/02
% v 2. 9/19/02
function [dh_dt,Q,V,Re,fd,iflag_main] = ...
tank_drain(h,fd_guess,Param,verbose,p_air,coef);
iflag_main = 0;
if(~exist('verbose'))
verbose = 0;
end
% open a file for writing
fid = fopen('Bernoulli_Eq.txt', 'a');
fprintf(fid,'\n Enter tank_drain \n\n');
Param.h = h; % tank water height in m - INPUT VALUE
% For this initial guess of the friction factor, we calculate
% the corresponding value of the velocity from the macroscopic
% energy balances.
V_guess = tank_drain_calc_V(fd_guess,Param,p_air,coef);
Re_guess = Param.density*V_guess*Param.Dp/Param.viscosity;
if(verbose)
disp(['Guess fd = ', num2str(fd_guess)]);
disp(['Guess velocity = ', num2str(V_guess)]);
disp(['Guess Reynolds'' number = ', num2str(Re_guess)]);
end
% Now, with this initial guess of the friction factor,
% we use the MATLAB command fzero to solve the resulting
% nonlinear algebraic equation for fd.
options = optimset('Display','off');
if(verbose)
options = optimset('Display','iter');
end
fprintf(fid,'\n V_guess= %5.3f Re= %6.0f fd_guess = %14.12f \n',...
V_guess, Re_guess, fd_guess);
fprintf(fid,'\n Into FZERO \n');
[fd,fval,exitflag,output] = fzero(@tank_drain_calc_f, ...
fd_guess,options,Param,p_air,coef);
% From the final value of the friction factor, we calculate
% the velocity through the pipe.
fprintf(fid,'\n Out of FZERO \n');
fprintf(fid,'\n fd_final = %14.12f \n', fd);
fprintf(fid,'\n Into tank_drain_calc_V\n');
V = tank_drain_calc_V(fd,Param,p_air,coef);
fprintf(fid,'\n Out of tank_drain_calc_V\n');
% the Reynolds' number
Re = Param.density*V*Param.Dp/Param.viscosity;
fprintf(fid,'\n V_final = %14.12f Re_final = %14.12f \n', V, Re );
% the volumetric flow rate through the drain pipe (m^3/2)
Q = pi/4*Param.Dp^2*V;
% the rate of change of the height of the tank (m/s)
dh_dt = -Q/(pi/4*Param.Dt^2);
fprintf(fid,'\n Exit tank_drain \n\n');
fclose(fid);
if(verbose)
disp(['Darcy friction factor = ', num2str(fd)]);
disp(['Drain pipe velocity (m/s) = ', num2str(V)]);
disp(['Pipe Reynolds'' number = ', num2str(Re)]);
disp(['Volumetric flow rate (m^3/s) = ', num2str(Q)]);
disp(['Rate of change of height (m/s) = ', num2str(dh_dt)]);
end
iflag_main = 1;
return;
% ===========================================================
% This MATLAB function calculates the velocity through the
% drain pipe as a function of the Darcy friction factor.
% K. Beers. MIT ChE. 9/18/02
function V = tank_drain_calc_V(fd,Param,p_air,coef);
var1 = p_air + coef.a2*Param.h - coef.a4;
var2 = coef.a3 + coef.a5 + coef.a6 + coef.a7*fd - coef.a1;
V = sqrt(var1/var2);
S = V^2;
Re = Param.density*V*Param.Dp/Param.viscosity;
% open a file for writing
fid = fopen('Bernoulli_Eq.txt', 'a');
fprintf(fid,'\n Calc_V %8.0f %7.3e %6.0f %8.0f %6.2f %6.2f', ...
p_air,coef.a1*S,coef.a2*Param.h,coef.a3*S,coef.a4,coef.a5);
fprintf(fid,' %2.1f %6.0f %7.4f %7.4f %7.0f\n\n', ...
coef.a6,coef.a7*fd*S,V,fd, Re );
fclose(fid);
return;
% ==========================================================
% This MATLAB function calculates the function values
% that goes to zero when the value of the Darcy
% friction factor satisfies the problem.
% K. Beers. MIT ChE. 9/18/02
% v. 2. 9/20/02
function fval = tank_drain_calc_f(x,Param,p_air,coef);
fd = x;
% For this value of the friction factor, calculate
% the corresponding velocity from the balance
% equations.
V = tank_drain_calc_V(fd,Param,p_air,coef);
% From this velocity, calculate the Reynolds' number
% in the pipe.
Re = Param.density*V*Param.Dp/Param.viscosity;
% If Re < 2100, laminar flow
if(Re < 2100)
fval = fd - 64/Re;
% else for turbulent flow, use Colebrook equation
else
fval = colebrook(Re,Param.e_D);
%******* This code works ******************************************
% var1 = Param.e_D/3.7 + 2.51/Re/sqrt(fd);
% fval = 1/sqrt(fd) + 2*log10(var1);
%******* This code works ******************************************
end
return;
function fval = colebrook(R,K);
% F = COLEBROOK(R,K) fast, accurate and robust computation of the
% Darcy-Weisbach friction factor F according to the Colebrook equation:
% - -
% 1 | K 2.51 |
% --------- = -2 * Log_10 | ----- + ------------- |
% sqrt(F) | 3.7 R * sqrt(F) |
% - -
% INPUT:
% R : Reynolds' number (should be >= 2300).
% K : Equivalent sand roughness height divided by the hydraulic
% diameter (default K=0).
%
% OUTPUT:
% F : Friction factor.
%
% FORMAT:
% R, K and F are either scalars or compatible arrays.
% Initialization.
X1 = K*R* 0.123968186335417556; % X1 <- K * R * log(10) / 18.574.
X2 = log(R) - 0.779397488455682028; % X2 <- log( R * log(10) / 5.02 );
% Initial guess.
F = X2 - 0.2;
% First iteration.
E = ( log(X1+F) - 0.2 )/ ( 1 + X1 + F );
F = F - (1+X1+F+0.5*E)*E*(X1+F)/ (1+X1+F+E*(1+E/3));
% Second iteration (remove the next two lines for moderate accuracy).
E = ( log(X1+F) + F - X2 ) / ( 1 + X1 + F );
F = F - (1 + X1 + F + 0.5*E)*E*( X1 + F )/( 1+X1 + F + E*(1+E/3));
% Finalized solution.
F = 1.151292546497022842/F; % F <- 0.5 * log(10) / F;
fval = F*F; % F <- Friction factor.
fid = fopen('Bernoulli_Eq.txt', 'a');
fprintf(fid,'\n\nRe = %8.0f e/D=K = %8.6f fval= %6.4f\n\n',R,K,fval );
fclose(fid);
return;