PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/matlab/codes/geophysic/convert_unit.m

http://guillaumemaze.googlecode.com/
MATLAB | 382 lines | 213 code | 48 blank | 121 comment | 41 complexity | b1703e3f22d4684eadd4bbf8b79c7dac MD5 | raw file
Possible License(s): GPL-3.0
  1. % convert_unit Convert unit of oceanic concentration substance
  2. %
  3. % NEW_SUBST_CONTENT = convert_unit(SUBST_CONTENT,SUBST_TYPE,UNIT_IN,UNIT_OUT,[SIG0,VERBOSE])
  4. %
  5. % Convert concentration of substance SUBST_CONTENT of type SUBST_TYPE
  6. % from UNIT_IN to UNIT_OUT.
  7. %
  8. % Inputs:
  9. % SUBST_CONTENT: a double array of any dimensions
  10. % SUBST_TYPE:
  11. % 'OXY' for Oxygen (O2)
  12. % 'PHOS' for Phosphate (PO4)
  13. % 'NITR' for Nitrate (NIO3)
  14. % 'NIO2' for Nitrite (NIO2)
  15. % 'SIO3' for Silicate (SIO3)
  16. % 'SIO4' for Silice (SIO4)
  17. % UNIT_IN is a string with format: NUMERATOR/DENOMINATOR with:
  18. % NUMERATOR = 'mol';'mmol';'mumol';'kg';'g';'mg';'l';'ml'
  19. % DENOMINATOR = 'kg';'g';'m3';'l';'ml'
  20. % Any combination is allowed.
  21. % UNIT_OUT: idem as UNIT_IN
  22. % SIG0 is a singleton or a double array of SUBST_CONTENT dimensions.
  23. % It contains the anomalous potential density referred to the sea
  24. % surface in kg/m3.
  25. % Conversion is computed with RHO = 1000 + SIG0.
  26. % If SIG0 not specified, it is set to 0.
  27. % VERBOSE (0/1) prints information about the conversion on screen (0 by default).
  28. %
  29. % Example:
  30. % convert_unit(300,'OXY','mumol/kg','ml/l',0,1)
  31. % convert_unit(9,'OXY','ml/l','mmol/l',32,1)
  32. %
  33. % Rq:
  34. % Molar mass (g/mol):
  35. % O = 15.9994; % Oxygen
  36. % P = 30.973762; % Phophorus
  37. % Si = 28.0855; % Silicon
  38. % N = 14.0067; % Nitrogen
  39. % (Source: http://www.iupac.org/publications/pac/2006/pdf/7811x2051.pdf)
  40. % Molar volume (l/mol):
  41. % OXY = 22.3916; % at standard temperature and pressure (Garcia and Gordon, 1992).
  42. % % Note that for an ideal gas it is: 22.413
  43. % ...
  44. % The molar volume for other substances is not documented right now, so any conversion from
  45. % mole to liter is impossible and will return NaN. Only mole <-> kg
  46. % Well, OXY is a gaz while other substances are ions, so it's not so surprising. Beside, most
  47. % current conversions are from mumol or mmol per m3 to per l and thus do not involved molar
  48. % volumes.
  49. %
  50. % Other source: http://www.helcom.fi/groups/monas/CombineManual/AnnexesB/en_GB/annex9app3/
  51. %
  52. % Created: 2009-09-16.
  53. % Copyright (c) 2009 Guillaume Maze.
  54. % http://codes.guillaumemaze.org
  55. %
  56. % This program is free software: you can redistribute it and/or modify it under the
  57. % terms of the GNU General Public License as published by the Free Software Foundation,
  58. % either version 3 of the License, or any later version. This program is distributed
  59. % in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
  60. % implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  61. % GNU General Public License for more details. You should have received a copy of
  62. % the GNU General Public License along with this program.
  63. % If not, see <http://www.gnu.org/licenses/>.
  64. %
  65. function varargout = convert_unit(varargin)
  66. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Input check
  67. % Number or arguments:
  68. error(nargchk(4,6,nargin));
  69. % Retrieve arguments:
  70. subst = varargin{1};
  71. subst_typ = varargin{2};
  72. subst_typ = upper(subst_typ);
  73. unit_in = varargin{3};
  74. a = strread(unit_in,'%s','delimiter','/');
  75. numerator_in = a{1};
  76. denominator_in = a{2};
  77. unit_out = varargin{4};
  78. a = strread(unit_out,'%s','delimiter','/');
  79. numerator_out = a{1};
  80. denominator_out = a{2};
  81. % Move from dm3 to l:
  82. numerator_in = dm3tol(numerator_in);
  83. denominator_in = dm3tol(denominator_in);
  84. numerator_out = dm3tol(numerator_out);
  85. denominator_out = dm3tol(denominator_out);
  86. % Check values:
  87. if ~check_subst(subst_typ),error(get_err(1));end
  88. if ~check_numerator(numerator_in),error(get_err(2));end
  89. if ~check_denominator(denominator_in),error(get_err(3));end
  90. if ~check_numerator(numerator_out),error(get_err(2));end
  91. if ~check_denominator(denominator_out),error(get_err(3));end
  92. % Density:
  93. if nargin >= 5
  94. rho = 1000 + varargin{5};
  95. else
  96. rho = 1000;
  97. end
  98. % Verbose operations:
  99. if nargin >= 6
  100. verb = varargin{6};
  101. else
  102. verb = 0;
  103. end
  104. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Conversion:
  105. if verb
  106. verb_coef(subst_typ);
  107. end
  108. coef1 = get_numer_factor(unit_in,unit_out,subst_typ,verb);
  109. coef2 = get_denom_factor(unit_in,unit_out,rho,verb);
  110. subst = subst.*coef1./coef2;
  111. if verb
  112. disp(sprintf('[output] = [input]*(1)/(2)'));
  113. end
  114. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  115. varargout(1) = {subst};
  116. end %function
  117. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  118. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MORE IMPORTANT SUBFUNCTIONS:
  119. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  120. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  121. function coef_list = get_coef_list(subst_typ)
  122. % coef_list(1): molar mass in g/mol
  123. % coef_list(2): molar density in g/l
  124. % coef_list(3): molar volume (l/mol) is thus: coef_list(1)/coef_list(2)
  125. % coef_list(4) = 1e3/coef_list(3);
  126. % Source: http://www.iupac.org/publications/pac/2006/pdf/7811x2051.pdf
  127. % Molar mass:
  128. O = 15.9994; % Oxygen
  129. P = 30.973762; % Phophorus
  130. Si = 28.0855; % Silicon
  131. N = 14.0067; % Nitrogen
  132. coef_list(1:2) = NaN;
  133. switch subst_typ
  134. case 'OXY'
  135. coef_list(1) = 2*O; % Molar mass g/mol
  136. coef_list(3) = 22.3916; % Molar volume l/mol (22.413 for a perfect gas)
  137. coef_list(2) = coef_list(1)/coef_list(3); % Molar density g/l
  138. coef_list(4) = 1e3/coef_list(3); % Never use here but from time to time in other routines of conversion
  139. % ACCORDING TO THE ARGO DATA MANAGEMENT USER'S MANUAL V2.2 OF AUG 26, 2009:
  140. % REMARK ON UNIT CONVERSION OF OXYGEN:
  141. % The unit of DOXY is micromole/kg in Argo data and the oxygen measurements are sent from
  142. % Argo floats in another unit such as micromole/L for Optode and ml/L for SBE. Thus the unit
  143. % conversion is carried out by DACs as follows:
  144. % ! O2 [micromole/kg] = O2 [micromole/L] / rho
  145. % ! O2 [micromole/L] = 44.6596 × O2 [ml/L]
  146. % Here, rho is the potential density of water [kg/L] at zero pressure and at the potential
  147. % temperature (e.g., 1.0269 kg/L; e.g., UNESCO, 1983). The value of 44.6596 is derived from
  148. % the molar volume of the oxygen gas, 22.3916 L/mole, at standard temperature and pressure
  149. % (0°C, 1 atmosphere; e.g., García and Gordon, 1992).
  150. % UNESCO (1983): Algorithms for computation of fundamental properties of seawater. Unesco
  151. % technical papers in marine science, 44, 53pp.
  152. case 'PHOS'
  153. coef_list(1) = P + 4*O;
  154. case 'NITR' % NO3
  155. coef_list(1) = N + 3*O;
  156. case 'NIO2'
  157. coef_list(1) = N + 2*O;
  158. case 'SIO3'
  159. coef_list(1) = Si + 3*O;
  160. case 'SIO4'
  161. coef_list(1) = Si + 4*O;
  162. end%switch
  163. end%function
  164. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  165. function subst_list = get_list_subst(varargin)
  166. subst_list = {'OXY';'PHOS';'NITR';'NIO2';'SIO3';'SIO4'};
  167. end
  168. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  169. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LOWER LEVEL SUBFUNCTIONS:
  170. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  171. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  172. function coef = get_numer_factor(unit_in,unit_out,subst_typ,verb)
  173. % Get coefficients appropriate for the substance
  174. coef_list = get_coef_list(subst_typ);
  175. a = strread(unit_in,'%s','delimiter','/');
  176. numerator_in = a{1};
  177. a = strread(unit_out,'%s','delimiter','/');
  178. numerator_out = a{1};
  179. if strcmp(numerator_out,'dm3'),numerator_out='l';end
  180. % Power of 10:
  181. c(1,:) = [ 0 ; 3 ; 6 ; -3 ; 0 ; 3 ; 0 ; 3 ]; % mol
  182. c(2,:) = [ 0 ; 0 ; 3 ; -6 ; -3 ; 0 ; -3 ; 0 ]; % mmol
  183. c(3,:) = [ 0 ; 0 ; 0 ; -9 ; -6 ; -3 ; -6 ; -3 ]; % mumol
  184. c(4,:) = [ 0 ; 0 ; 0 ; 0 ; 3 ; 6 ; 3 ; 6 ]; % kg
  185. c(5,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 3 ; 0 ; 3 ]; % g
  186. c(6,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -3 ; 0 ]; % mg
  187. c(7,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 3 ]; % l
  188. c(8,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ]; % ml
  189. c = c - transpose(c); % Ensure symetry, we only filled the upper right
  190. % if ~isempty(find(tril(c)+triu(c)'~=0)),error(get_err(4));end % Check symetry
  191. % if ~isempty(find(c+transpose(c)~=0)),error(get_err(4));end % Check symetry
  192. % Power of molar mass (g/mol):
  193. d(1,:) = [ 0 ; 0 ; 0 ; 1 ; 1 ; 1 ; 1 ; 1 ];
  194. d(2,:) = [ 0 ; 0 ; 0 ; 1 ; 1 ; 1 ; 1 ; 1 ];
  195. d(3,:) = [ 0 ; 0 ; 0 ; 1 ; 1 ; 1 ; 1 ; 1 ];
  196. d(4,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  197. d(5,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  198. d(6,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  199. d(7,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  200. d(8,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  201. d = d - transpose(d); % Ensure symetry, we only filled the upper right
  202. % Power of molar density:
  203. g(1,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -1 ; -1 ];
  204. g(2,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -1 ; -1 ];
  205. g(3,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -1 ; -1 ];
  206. g(4,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -1 ; -1 ];
  207. g(5,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -1 ; -1 ];
  208. g(6,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; -1 ; -1 ];
  209. g(7,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  210. g(8,:) = [ 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ];
  211. g = g - transpose(g); % Ensure symetry, we only filled the upper right
  212. %
  213. numer_list = get_list_numerator;
  214. for iin =1:length(numer_list),if strcmp(numer_list{iin},numerator_in), break;end;end
  215. for iout=1:length(numer_list),if strcmp(numer_list{iout},numerator_out),break;end;end
  216. coef = 10.^c(iin,iout);
  217. opr_str = sprintf('10^%i',c(iin,iout));
  218. if d(iin,iout)~=0
  219. coef = coef*coef_list(1).^d(iin,iout);
  220. opr_str = sprintf('%s * c1^%i',opr_str,d(iin,iout));
  221. end
  222. if g(iin,iout)~=0,
  223. coef = coef*coef_list(2).^g(iin,iout);
  224. opr_str = sprintf('%s * c2^%i',opr_str,g(iin,iout));
  225. end
  226. if verb,disp(sprintf('(1) [%s] = [%s] * %s',numerator_out,numerator_in,opr_str));end
  227. end%function
  228. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  229. function coef = get_denom_factor(unit_in,unit_out,rho,verb)
  230. a = strread(unit_in,'%s','delimiter','/');
  231. denominator_in = a{2};
  232. if strcmp(denominator_in,'dm3'),denominator_in='l';end
  233. a = strread(unit_out,'%s','delimiter','/');
  234. denominator_out = a{2};
  235. if strcmp(denominator_out,'dm3'),denominator_out='l';end
  236. % Power of 10:
  237. c(1,:) = [ 0 ; 3 ; 0 ; 3 ; 6 ];
  238. c(2,:) = [ -3 ; 0 ; 3 ; 6 ; 9 ];
  239. c(3,:) = [ 0 ; -3 ; 0 ; 3 ; 6 ];
  240. c(4,:) = [ -3 ; -6 ; -3 ; 0 ; 3 ];
  241. c(5,:) = [ -6 ; -9 ; -6 ; -3 ; 0 ];
  242. % Power of rho:
  243. d(1,:) = [ 0 ; 0 ; -1 ; -1 ; -1 ];
  244. d(2,:) = [ 0 ; 0 ; -1 ; -1 ; -1 ];
  245. d(3,:) = [ 1 ; 1 ; 0 ; 0 ; 0 ];
  246. d(4,:) = [ 1 ; 1 ; 0 ; 0 ; 0 ];
  247. d(5,:) = [ 1 ; 1 ; 0 ; 0 ; 0 ];
  248. %
  249. denom_list = get_list_denominator;
  250. for iin =1:length(denom_list),if strcmp(denom_list{iin},denominator_in), break;end;end
  251. for iout=1:length(denom_list),if strcmp(denom_list{iout},denominator_out),break;end;end
  252. coef = 10.^c(iin,iout);
  253. opr_str = sprintf('10^%i',c(iin,iout));
  254. if d(iin,iout)~=0,
  255. coef = coef*rho.^d(iin,iout);
  256. opr_str = sprintf('%s * rho^%i',opr_str,d(iin,iout));
  257. end
  258. if verb,disp(sprintf('(2) [%s] = [%s] * %s',denominator_out,denominator_in,opr_str));end
  259. end%function
  260. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  261. function N = avogadro(varargin)
  262. N = 6.02214179*1e23;
  263. end%function
  264. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  265. function varargout = verb_coef(subst_typ)
  266. coef_list = get_coef_list(subst_typ);
  267. disp('For molar species, volume unit is liter');
  268. for ii = 1 : length(coef_list)
  269. if ~isnan(coef_list(ii))
  270. switch ii
  271. case 1, disp(sprintf('Molar Mass : c1 = %2.6f g/mol',coef_list(ii)));
  272. case 2, disp(sprintf('Molar Density : c2 = %2.6f g/l',coef_list(ii)));
  273. case 3, disp(sprintf('Molar Volume : c3 = %2.6f l/mol (Molar Mass/Density <=> c1/c2)' ,coef_list(ii)));
  274. case 4, disp(sprintf('Misc. coef. : c4 = %2.6f mmol/l (10^3 / Molar volume <=> 1e3*c2/c1)' ,coef_list(ii)));
  275. end
  276. end
  277. end%for ii
  278. end%function
  279. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  280. function res = check_subst(subst)
  281. subst_list = get_list_subst;
  282. if isempty(cell2mat(strfind(subst_list,subst)))
  283. res = false;
  284. else
  285. res = true;
  286. end
  287. end
  288. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  289. function res = check_denominator(unit)
  290. unit_list = get_list_denominator;
  291. if isempty(cell2mat(strfind(unit_list,unit)))
  292. res = false;
  293. else
  294. res = true;
  295. end
  296. end
  297. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  298. function unit_list = get_list_denominator(varargin)
  299. unit_list = {'kg';'g';'m3';'l';'ml'};
  300. end
  301. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  302. function res = check_numerator(unit)
  303. unit_list = get_list_numerator;
  304. if isempty(cell2mat(strfind(unit_list,unit)))
  305. res = false;
  306. else
  307. res = true;
  308. end
  309. end
  310. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  311. function unit_list = get_list_numerator(varargin)
  312. unit_list = {'mol';'mmol';'mumol';'kg';'g';'mg';'l';'ml'};
  313. end
  314. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  315. function str = dm3tol(str);
  316. if strcmp(str,'dm3'), str = 'l'; end
  317. end%function
  318. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  319. function msgstruct = get_err(id,varargin)
  320. switch id
  321. case 1
  322. msgstruct.identifier = 'convert_unit:substance_unknown';
  323. msgstruct.message = 'Unknown substance !';
  324. case 2
  325. msgstruct.identifier = 'convert_unit:unit_numerator_unknown';
  326. msgstruct.message = 'Unit at numerator not supported !';
  327. case 3
  328. msgstruct.identifier = 'convert_unit:unit_denominator_unknown';
  329. msgstruct.message = 'Unit at denominator not supported !';
  330. case 4
  331. msgstruct.identifier = 'convert_unit:conversion_matrix';
  332. msgstruct.message = 'Conversion matrix inconsistent';
  333. end
  334. end