function varargout = ita_constants( varargin ) %ITA_CONSTANTS - Calculate acoustic constants % % Syntax: varargout = ita_constants(what, Options) % Options (default): % medium (air): medium of interest % T (293.16): temperatur in K or C (Values below 100 will be interpreted as C) % f (1000): Frequency of interrest (only affects m) can be a vector % p (101325): static pressure in Pa % phi (0.1): relative humidity [0 - 1] % % Example: c = ita_constants('c'); % [c, m] = ita_constants({'c','m'},'medium','air', 'T', 15, 'f',[100 200 400 1000], 'p', 101300); % % Currently supportet constants: % all - returns structure with all constants % c - speed of sound % m - attenuation constant % rho_0 - density % z_0 = rho_0 * c - characteristic impedance % p_b or p_0 - reference pressure for calculation of sound pressure level % % (air atenuation according to ISO 9613-1 and paper by Bass, et al., % "Atmospheric absorption of sound", JASA, January 1995.) % % See also ita_roomacoustics, itaValue % % Reference page in Help browser % doc ita_sabine % % This file is part of the ITA-Toolbox. Some rights reserved. % You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder. % % Author: Roman Scharrer -- Email: rsc@akustik.rwth-aachen.de % Created: 02-Feb-2009 %% Get ITA Toolbox preferences and Function String sArgs = struct('pos1_what','anything','medium','air','T',293.16,'f',1000,'p',101325, 'phi', 0.5); % Temperature, % Frequency, Static air pressure, Rel. Humidity thisFuncStr = [upper(mfilename) ':']; if nargin > 0 sArgs = ita_parse_arguments(sArgs,varargin); else sArgs.what = {'all'}; end if ischar(sArgs.what) sArgs.what = {sArgs.what}; end if sArgs.T < 100 sArgs.T = 273.15 + sArgs.T; %Celsius to Kelvin ita_verbose_info([thisFuncStr 'conversion of Celsius to Kelvin.'],1) end if sArgs.phi > 1 || sArgs.phi < 0 error('Invalid range for relative humidity PHI. It has to be in range 0...1.') end sArgs.f = itaValue(sArgs.f,'Hz'); sArgs.T = itaValue(sArgs.T,'K'); sArgs.p = itaValue(sArgs.p,'Pa'); sArgs.phi = itaValue(sArgs.phi,''); persistent constants if ~isempty(constants) tEqual = false; if numel(double(constants.T)) == numel(double(sArgs.T)) && all(double(constants.T) == double(sArgs.T)) tEqual = true; end phiEqual = false; if numel(double(constants.phi)) == numel(double(sArgs.phi)) && all(double(constants.phi) == double(sArgs.phi)) phiEqual = true; end fEqual = false; if numel(double(constants.f)) == numel(double(sArgs.f)) && all(double(constants.f) == double(sArgs.f)) fEqual = true; end pEqual = false; if numel(double(constants.p_stat)) == numel(double(sArgs.p)) && all(double(constants.p_stat) == double(sArgs.p)) pEqual = true; end allIsWell = tEqual && phiEqual && fEqual && pEqual; else allIsWell = false; end if ~allIsWell %pdi: performance reasons %% set some constants switch lower(sArgs.medium) case {'luft','air'} T_0 = itaValue(273.15,'K'); % Zero-Temperature (in K) T_r = itaValue(20,'K') + T_0; % Reference Temperature (equiv. 20 C) p_r = itaValue(101325,'Pa'); % Reference static pressure (in Pa) % calculate molar concentration of water (h) in air (in percent) % use new version V = -6.8346*(T_0/sArgs.T)^1.261+4.6151; p_sat = p_r*10^V; % stauration vapor pressure h = 100*sArgs.phi*p_sat/sArgs.p; % molar concentration of water vapor in percent M_r = itaValue(0.0289644,'kg/mol'); % molar mass of dry air R_mol = itaValue(8.31,'N m/(mol*K)'); % molar gas constant for air R_l = R_mol/M_r; % [J/(kg*K)] gas constant for dry air R_d = itaValue(461,'J/kg*K'); % gas constant of water vapor R_f = R_l/(1-(h/100)*(1-R_l/R_d)); % [J/(kg K)] gas constant for air with relative humidity phi kappa = 1.4; % heat capacity ratio nu = itaValue(0.0261,'W/(m*K)');%#ok % heat conductivity C_v = itaValue(718,'J/(kg*K)');%#ok % specific heat capacity rho_0 = sArgs.p/(R_f*sArgs.T); % air density eta = itaValue(17.1*1e-6,'Pa*s');%#ok % air viscosity (at 273K) p_b = itaValue(2*10^(-5),'Pa');% - reference pressure for SPL otherwise error([thisFuncStr ' I dont know that medium yet, please teach me!']); end %% include input parameter T, phi, f and p_stat constants.T = sArgs.T; constants.phi = sArgs.phi; constants.f = sArgs.f; constants.p_stat = sArgs.p; %% Speed of sound constants.c = sqrt(kappa*R_f*sArgs.T); c = constants.c; %% Air attenuation % the formulas are according to Bass, the units really do not make sense % relaxation frequencies for oxygen and nitrogen (dimensionless ???) frO = double((sArgs.p/p_r).*(24 + 4.04e4.*h.*(0.02 + h)./(0.391 + h))); frN = double((sArgs.p./p_r).*(sArgs.T./T_r).^(-1/2).*(9 + 280.*h.*exp(-4.17.*((sArgs.T./T_r).^(-1/3) - 1)))); % m (1/m), factor 2 comes from conversion Neper -> dB -> linear m = 2.*double(sArgs.f).^2.*(double(1.84e-11.*double(p_r./sArgs.p).*double(sArgs.T/T_r)^(1/2)) + ... double(sArgs.T/T_r)^(-5/2).*(0.01275.*exp(-2239.1./double(sArgs.T)).*frO./(frO.^2 + double(sArgs.f).^2) + ... 0.1068.*exp(-3352./double(sArgs.T)).*frN./(frN.^2+double(sArgs.f).^2))); % this is a linear factor, to convert to dB/m multiply by 10*log10(e)=4.34 constants.m = itaValue(m,'1/m'); %% Density constants.rho_0 = rho_0; %% Z_0 constants.z_0 = rho_0*c; %% p_b constants.p_b = p_b; constants.p_0 = p_b; %% P_0/P_b constants.P_b = itaValue(1e-12,'W'); constants.P_0 = itaValue(1e-12,'W'); end %% set output arguments if ~nargout % plot that thang! disp('Your constants are:'); fields = fieldnames(constants); fieldStr = char(fields); constantsStr = cell(numel(fields),1); for i=1:numel(fields) cons = constants.(fields{i}); if numel(cons.value) > 1 constantsStr{i} = ['<' num2str(numel(cons.value)) ' values> ' cons.unit]; else constantsStr{i} = num2str(cons); end end disp([fieldStr repmat(' : ',numel(fields),1) char(constantsStr)]); end for idx = 1:numel(sArgs.what) if isfield(constants,lower(sArgs.what{idx})) varargout{idx} = constants.(sArgs.what{idx}); %#ok elseif strcmpi(sArgs.what{idx},'all') varargout{idx} = constants; %#ok else error([thisFuncStr ' I dont know that constant yet, please teach me!']); end end