功能" fzero"在退出时返回一个奇怪的值NaN

时间:2017-02-22 18:28:13

标签: matlab

当退出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;

0 个答案:

没有答案