Написанная мной функция
[mass,matStoichCoeff,elChem1]=formula(A0,elChem1_0)
для списка веществ A0 выводит молярную массу mass, при необходимости матрицу стехиометрических коэффициентов matStoichCoeff и соответствующий этой матрице список химических элементов elChem1. Стехиометрическая матрица – это число атомов элемента в каждом веществе. Если для стехиометрической матрицы нас интересуют конкретные элементы в исходном списке, можно задать их через elChem1_0. Если в введённой формуле для одного вещества более одной звёздочки/точки и/или неправильно расставлены скобки, программа выдаст ошибку.
Вводим исходный список веществ A0 в таком формате:
A0={'FeO(OH)' 'H2O' 'PbSO4*7H2O' 'CuSO4·5H2O' 'K3[Al(OH)6]' ...
'Ca(H2PO4)2' 'CO2' '(Fe(OH)2)2SO4' 'Ca(H2PO4)2*12H2O'}.
Данный список - пример для расчётов.
Пример 1. При выполнении
mass=formula(A0)
получаем:
Пример 2. Для того же исходного списка, теперь нас интересует и матрица, и список всех элементов для исходного списка веществ:
[mass,A,r]=formula(A0)
Получаем:
Пример 3. Если интересует, сколько атомов конкретных элементов в каждом веществ, например, элементы {'C' 'O'}:
[mass,A,r]=formula(A0,{'C' 'O'})
получаем:
А вот и сама функция:
function [mass,matStoichCoeff,elChem1]=formula(A0,elChem1_0)
% mass - молярная масса
% matStoichCoeff - матрица стехиометрических коэффициентов
% elChem1 - элементы
% A0 – список веществ;
% ==================
elChem={'H' 'He' 'Li' 'Be' 'B' 'C' 'N' 'O' 'F' 'Ne' 'Na' 'Mg' 'Al' 'Si' 'P' 'S' 'Cl' 'Ar' 'K' 'Ca' ...
'Sc' 'Ti' 'V' 'Cr' 'Mn' 'Fe' 'Co' 'Ni' 'Cu' 'Zn' 'Ga' 'Ge' 'As' 'Se' 'Br' 'Kr' 'Rb' 'Sr' 'Y' 'Zr' 'Nb' 'Mo' 'Tc' 'Ru' ...
'Rh' 'Pd' 'Ag' 'Cd' 'In' 'Sn' 'Sb' 'Te' 'I' 'Xe' 'Cs' 'Ba' 'La' 'Ce' 'Pr' 'Nd' 'Pm' 'Sm' 'Eu' 'Gd' 'Tb' 'Dy' 'Ho' 'Er' ...
'Tm' 'Yb' 'Lu' 'Hf' 'Ta' 'W' 'Re' 'Os' 'Ir' 'Pt' 'Au' 'Hg' 'Tl' 'Pb' 'Bi' 'Po' 'At' 'Rn' 'Fr' 'Ra' 'Ac' 'Th' 'Pa' 'U' ...
'Np' 'Pu' 'Am' 'Cm' 'Bk' 'Cf' 'Es' 'Fm' 'Md' 'No' 'Lr' 'Ku' 'Ns'};
elMassNum=[1.008 4.0026 6.941 9.0123 10.81 12.011 14.0067 15.9994 18.9994 20.179...
22.98977 24.305 26.98154 28.0855 30.97376 32.06 35.453 39.948 39.0983 40.08...
44.9559 47.9 50.9415 51.996 54.938 55.847 58.9332 58.7 63.546 65.38 69.72 72.59...
74.9216 78.96 79.904 83.8 85.4678 87.62 88.9059 91.22 92.9064 95.94 98 101.07...
102.9055 106.4 107.868 112.41 114.82 118.69 121.75 127.6 126.9045 131.3 132.9054...
137.33 138.9055 140.12 140.9077 144.24 145 150.4 151.96 157.25 158.9254 162.5...
164.9304 167.26 168.9342 173.04 174.967 178.49 180.9478 183.85 186.207 190.2 192.22...
195.09 196.9665 200.59 204.37 207.2 208.9804 209 210 222 223 226.0254 227.0278...
232.0381 231.0359 238.029 237.0482 244 243 247 247 251 252 257 258 259 260 261 262];
% ----------------------
if nargout>1
m=length(A0); % количество столбцов
n=length(elChem); % количество строк
matStoichCoeff=zeros(n,m);
end
% ------------------------------------------------
for ii=1:length(A0)
A=A0(ii);
cc=char(A);cc0=cc;
c=double(cc);
c(c==91)=40; c(c==93)=41;
% -------------------
indL1=c>64 & c<91;
indL2=c>96 & c<123;
indL=[(indL1(1:end-1)+indL2(2:end))==2,0];
letter1=cc(indL1);
ind1=[0,indL1(1:end-1)];
letter2=cc(ind1~=0);
ind=indL(indL1~=0);
EL=[];numCh=[];
for j=1:length(letter1)
if ind(j)~=0
EL0={letter1(j),letter2(j)};
else
EL0={letter1(j)};
end
EL=[EL,{EL0}];
numCh=[numCh,strmatch(EL0, elChem, 'exact')];
end
at_mass=elMassNum(numCh);
% -----------------
cc([0,indL]~=0)=[];c([0,indL]~=0)=[];
indD=c>47 & c<58;
indL=c>64 & c<91;
%-------------------------------------
I=[indD,0]; N=length(I);
ss0=sign(I);
NN0=1:N;I00=NN0*0;
in1=NN0(ss0(1:end-1)~=ss0(2:end));
l=length(in1);
num1=(1:N)*0+1;
while l>1
I0=I00;
I0(in1(1)+1:in1(2))=I(in1(1)+1:in1(2));
num0=str2double(cc(I0~=0));
if isempty(num0)==0
num1(in1(1))=num0;
end
in1(1)=[];
l=l-1;
end
num=num1(indL);
num00=(1:N-1)*0;num00(indL)=num;
% --------------скобки-------
indBrac1=c==40; indBrac2=c==41;
liu=sum(indBrac1);
if liu~=sum(indBrac2)
error(['Некорректно введённая формула: ',cc0])
end
N=length(c);NN0=1:N;
while liu>0
c1=c;
c1(indBrac1==0 & indBrac2==0)=0;
in=NN0(c1~=0);
c1(c1==0)=[];
% ----------------------------------
liu0=(c1(1:end-1)==40 & c1(2:end)==41);
liu1=[liu0,0];liu2=[0,liu0];
liu1=in(liu1~=0);liu2=in(liu2~=0);
for k=1:sum(liu0)
num00(liu1(k):liu2(k))=num00(liu1(k):liu2(k))*num1(liu2(k));
indBrac1(liu1(k))=0;
indBrac2(liu2(k))=0;
end
liu=sum(indBrac1);
end
% ---------звёздочка-----------------------
indStar=(c==42 | c==183); % ( * or ·)
if sum(indStar)==1
indd=NN0(indStar);
num00(indd:end)=num00(indd:end)*num1(indStar);
end
if sum(indStar)>1
error(['Некорректно введённая формула: ',cc0])
end
% ---------------------------------------
num00=num00(indL);
mass(ii)=at_mass*num00';
% -------матрица стехеометрических коэффициентов---------------
if nargout>1
while isempty(numCh)==0
ind=numCh(1);
rt=(numCh==numCh(1));
numC=sum(num00(rt));
matStoichCoeff(ind,ii)=numC;
numCh(rt)=[];num00(rt)=[];
end
end
% --------------------------------------------------
end
% -------матрица стехеометрических коэффициентов---------------
if nargout>1
if nargin > 1
for i=1:length(elChem1_0)
ind(i)=strmatch(elChem1_0(i),elChem,'exact');
end
elChem1=elChem(ind);
matStoichCoeff=matStoichCoeff(ind,:);
else
elChem1=elChem';
elChem1(sum(matStoichCoeff,2)==0)=[];
matStoichCoeff((sum(matStoichCoeff,2)==0),:)=[];
end
end
% ---------------------------------------------------