unit UnitGaussJordan;

{$mode objfpc}{$H+}

interface
uses pivotgauss,SysUtils,gibbs,math;

procedure DetermineReactions(aa:matricereelle;  bb:tableaureel;
nombre_especes,nombre_type_atomes_gj:longint;
noms_1,f_b_1:tableaustring;
var rang,reac:longint;
var reactions,equations_conservation,equations_avancements: tableaustring;
var aaa:matricereelle; var b:tableaureel;
var coeff_stoechio:matricereelle;
potentiel_standard:tableaureel;
var deltarG0,logK:tableaureel;
temperature:float);

procedure DetermineReactionsAnnexe(aa:matricereelle;  bb:tableaureel;
nombre_especes,nombre_type_atomes_gj:longint;
noms_1,f_b_1:tableaustring;
var rang,reac:longint;
var reactions,equations_conservation: tableaustring;
var aaa:matricereelle; var bbb:tableaureel;
var coeff_stoechio:matricereelle;
potentiel_standard:tableaureel;
var deltarG0:tableaureel;
temperature:float);

procedure DetermineMu0(coefficient_stoechiometriques:matricereelle;
logk:tableaureel; var mu0:tableaureel; nombre_especes,nombre_reactions:
integer; temperature:float);

procedure multiplieligne(var ma:matricereelle; ii:longint; x:float;
nombre_especes:longint);
 procedure ajouteligne(var ma:matricereelle; ii,jj:longint; x:float;
nombre_especes:longint);
 procedure permutecolonnes(var ma:matricereelle; ii,jj:longint;
 nombre_type_atomes_gj:longint);
 procedure permutelignes(var ma:matricereelle; ii,jj:longint;
 nombre_especes:longint);
procedure permutenoms(var nono:tableaustring; ii,jj:longint);
 function MinEntier(a,b:longint):longint;
 procedure permutereels(var nono:tableaureel; ii,jj:longint);
  procedure permuteentiers(var nono:tableauentier; ii,jj:longint);
procedure VerifieMatriceNulle(var a:matricereelle; nombre_especes,nombre_type_atomes_gj:integer);
function MyFrac(x:float):float;
function EstEntier(x,maxfrac:float): boolean;
function presentdanstableauentier(elementachercher:integer; dansqueltableau:tableauentier;
nombreelementsdutableau:integer; var saplace:integer):boolean;

implementation

function presentdanstableauentier(elementachercher:integer; dansqueltableau:tableauentier;
nombreelementsdutableau:integer; var saplace:integer):boolean;
var i:integer;
begin
if nombreelementsdutableau=0 then begin
result:=false;
exit;
end;
i:=0;
repeat
inc(i);
until ((i=nombreelementsdutableau) or (dansqueltableau[i-1]=elementachercher));
result:= ((i<nombreelementsdutableau) or
(dansqueltableau[nombreelementsdutableau-1]=elementachercher))  ;
saplace:=i;
end;



function MyFrac(x:float):float;
begin
result:=abs(abs(x)-round(abs(x)));
end;

function EstEntier(x,maxfrac:float): boolean;
 begin
 result:= (MyFrac(x)<maxfrac);
 end;

 function MinEntier(a,b:longint):longint;
 begin
 if a<b then result:=a else result:=b;
 end;

procedure multiplieligne(var ma:matricereelle; ii:longint; x:float;
nombre_especes:longint);
var kk:longint;
begin
for kk:=1 to nombre_especes do
ma[ii-1,kk-1]:=ma[ii-1,kk-1]*x;
end;


 procedure ajouteligne(var ma:matricereelle; ii,jj:longint; x:float;
nombre_especes:longint);
var kk:longint;
begin
for kk:=1 to nombre_especes do
ma[ii-1,kk-1]:=ma[ii-1,kk-1]+x*ma[jj-1,kk-1];
end;

procedure permutecolonnes(var ma:matricereelle; ii,jj:longint;
 nombre_type_atomes_gj:longint);
 var kk:longint; x:float;
 begin
 for kk:=1 to nombre_type_atomes_gj do begin
 x:=ma[kk-1,ii-1];
 ma[kk-1,ii-1]:=ma[kk-1,jj-1];
 ma[kk-1,jj-1]:=x;
 end;
 end;




  procedure permutelignes(var ma:matricereelle; ii,jj:longint;
 nombre_especes:longint);
  var kk:longint; x:float;
 begin
 for kk:=1 to nombre_especes do begin
 x:=ma[ii-1,kk-1];
 ma[ii-1,kk-1]:=ma[jj-1,kk-1];
 ma[jj-1,kk-1]:=x;
 end;
 end;




 procedure permutenoms(var nono:tableaustring; ii,jj:longint);
 var s:string;
 begin
 s:=nono[ii-1];
 nono[ii-1]:=nono[jj-1];
 nono[jj-1]:=s;
 end;


  procedure permutereels(var nono:tableaureel; ii,jj:longint);
 var s:float;
 begin
 s:=nono[ii-1];
 nono[ii-1]:=nono[jj-1];
 nono[jj-1]:=s;
 end;


  procedure permuteentiers(var nono:tableauentier; ii,jj:longint);
 var s:longint;
 begin
 s:=nono[ii-1];
 nono[ii-1]:=nono[jj-1];
 nono[jj-1]:=s;
 end;


procedure VerifieMatriceNulle(var a:matricereelle; nombre_especes,nombre_type_atomes_gj:integer);
var  fracmax:float;
var i,j:integer;
begin
fracmax:=1e-10;
for i:=1 to nombre_type_atomes_gj do
for j:=1 to nombre_especes do
if EstEntier(a[i-1,j-1],fracmax) then a[i-1,j-1]:=round(a[i-1,j-1]);
end;


procedure DetermineReactionsAnnexe(aa:matricereelle;  bb:tableaureel;
nombre_especes,nombre_type_atomes_gj:longint;
noms_1,f_b_1:tableaustring;
var rang,reac:longint;
var reactions,equations_conservation: tableaustring;
var aaa:matricereelle; var bbb:tableaureel;
var coeff_stoechio:matricereelle;
potentiel_standard:tableaureel;
var deltarG0:tableaureel;
temperature:float);
var i,j,k:longint; trouve,coefentiers,reaction_ne_compte_pas,bon_facteur:boolean;
s1,s2:string;   fracmax,facteur,facteur_actuel,toto:float;
  a,coefficients_stoechiometriques:matricereelle;
places_especes:tableauentier; noms,f_b:tableaustring;
label 3012,3017,3052,444,1024;

begin
fracmax:=1e-10;
rang:=0;
 facteur:=1;
 setlength(a,nombre_type_atomes_gj,nombre_especes);
 setlength(bbb,nombre_type_atomes_gj);
 {a:=copy(aa);}
 for i:=1 to nombre_especes do
 for j:=1 to  nombre_type_atomes_gj do
 a[j-1,i-1]:=aa[j-1,i-1];
    {bbb:=copy(bb);}
    for i:=1 to  nombre_type_atomes_gj do bbb[i-1]:=bb[i-1];
 setlength(places_especes,nombre_especes);
 for i:=1 to nombre_especes do places_especes[i-1]:=i;

 setlength(noms,nombre_especes);
 for i:=1 to  nombre_especes do
 noms[i-1]:=noms_1[i-1];
 setlength(f_b,nombre_especes);
 for i:=1 to  nombre_especes do
 f_b[i-1]:=f_b_1[i-1];

 coefentiers:=true;
 for i:=1 to nombre_especes do
 for j:=1 to nombre_type_atomes_gj do
 coefentiers:=coefentiers and EstEntier(a[j-1,i-1],fracmax);


 for i:=1 to MinEntier(nombre_especes,nombre_type_atomes_gj) do begin
 verifiematricenulle(a,nombre_especes,nombre_type_atomes_gj);


  {cas ou le pivot est nul: on cherche quelles lignes et colonnes permuter}
  if (a[i-1,i-1]=0) then begin

    trouve:=false;


      if  ((i<=nombre_especes) and (i<nombre_type_atomes_gj)) then begin
    k:=i;
    for j:=i+1 to nombre_type_atomes_gj do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end; end;

     if  ((i<nombre_especes) and (i<=nombre_type_atomes_gj)) then begin
    j:=i;
    for k:=i+1 to nombre_especes do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end;     end;


        if  ((i<nombre_especes) and (i<nombre_type_atomes_gj)) then
    for k:=i+1 to nombre_especes do
    for j:=i+1 to nombre_type_atomes_gj do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end;

          if  ((i=nombre_especes) and (i=nombre_type_atomes_gj)) then goto 3012;


    if not(trouve) then goto 3012;
    1024: permutelignes(a,i,j,nombre_especes);
           permutecolonnes(a,i,k,nombre_type_atomes_gj);
  permutenoms(noms,i,k);
  permutenoms(f_b,i,k);
  permutereels(bbb,i,j);
  permuteentiers(places_especes,i,k);
  end; {du cas pivot nul}



  if a[i-1,i-1]=1 then inc(rang);
  if a[i-1,i-1]<>1 then begin
  if (coefentiers and (abs(a[i-1,i-1])>1)) then facteur:=facteur*abs(a[i-1,i-1]);
   bbb[i-1]:=bbb[i-1]/a[i-1,i-1];
  multiplieligne(a,i,1/a[i-1,i-1],nombre_especes);
                                   inc(rang);
    end;

 if i>1 then for j:=1 to i-1 do
 if a[j-1,i-1]<>0 then begin
  bbb[j-1]:=bbb[j-1]-a[j-1,i-1]*bbb[i-1];
 ajouteligne(a,j,i,-a[j-1,i-1],nombre_especes);
        end;

  if i<nombre_type_atomes_gj then for j:=i+1 to nombre_type_atomes_gj do
 if a[j-1,i-1]<>0 then  begin
 bbb[j-1]:=bbb[j-1]-a[j-1,i-1]*bbb[i-1];
 ajouteligne(a,j,i,-a[j-1,i-1],nombre_especes);
   end;
 end;
 3012:
  setlength(reactions,nombre_especes-rang);
  setlength(coefficients_stoechiometriques,
  nombre_especes-rang,nombre_especes);
  reac:=0;
  for i:=1 to nombre_especes-rang do begin
  reaction_ne_compte_pas:=true;
  for j:=1 to rang do reaction_ne_compte_pas:=
  reaction_ne_compte_pas and (a[j-1,rang+i-1]=0);
  if reaction_ne_compte_pas then goto 3017;
  inc(reac);
  facteur_actuel:=1;
  {recherche du facteur pour avoir des coef entiers}
  if facteur>1 then
  for k:=1 to round(facteur) do begin
  bon_facteur:=true;
  for j:=1 to rang do
  bon_facteur:=bon_facteur and
  EstEntier(k*a[j-1,rang+i-1],fracmax);
  if bon_facteur then begin
  facteur_actuel:=k;
  goto 3052;
  end;
  end;
  3052:
  for j:=1 to rang do begin
    coefficients_stoechiometriques[reac-1,j-1]:=-a[j-1,rang+i-1]*facteur_actuel;
if EstEntier(coefficients_stoechiometriques[reac-1,j-1],fracmax) then
coefficients_stoechiometriques[reac-1,j-1]:=
round(coefficients_stoechiometriques[reac-1,j-1]);
end;
   coefficients_stoechiometriques[reac-1,rang+i-1]:=facteur_actuel;
if EstEntier(coefficients_stoechiometriques[reac-1,rang+i-1],fracmax) then
coefficients_stoechiometriques[reac-1,rang+i-1]:=
round(coefficients_stoechiometriques[reac-1,rang+i-1]);
   3017:
   end;

   for i:=1 to reac do begin
   s1:=''; s2:='';
   for j:=1 to nombre_especes do begin
   if coefficients_stoechiometriques[i-1,j-1]<0 then
   if s1<>'' then
   if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then s1:=s1+' + '+floattostr(-coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
   s1:=s1+' + '+noms[j-1]
   else
   if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then
   s1:=floattostr(-coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
   s1:=noms[j-1];

   if coefficients_stoechiometriques[i-1,j-1]>0 then
   if s2<>'' then
    if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then
   s2:=s2+' + '+floattostr(coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
     s2:=s2+' + '+noms[j-1]
   else
    if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then
   s2:=floattostr(coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
    s2:=noms[j-1] ;
   end;

   reactions[i-1]:=s1+' = '+s2;
   end;
    setlength(reactions,reac);


{recherche du facteur pour avoir des coef entiers}
  if facteur>1 then
  for j:=1 to rang do begin
    for k:=1 to round(facteur) do begin
  bon_facteur:=true;
  for i:=1 to nombre_especes do
  bon_facteur:=bon_facteur and
  EstEntier(k*a[j-1,i-1],fracmax);
  if bon_facteur then begin
   for i:=1 to nombre_especes do begin
   a[j-1,i-1]:=k*a[j-1,i-1];
 if EstEntier(a[j-1,i-1],fracmax) then
   a[j-1,i-1]:=round(a[j-1,i-1]);
   end;
   bbb[j-1]:=k*bbb[j-1];
   goto 444;
     end;             {du cas bon facteur}
      end;
      {de la boucle en k}
      444:
      end;{de la boucle en j}


       setlength(equations_conservation,rang);
 for i:=1 to rang do begin
 s1:='';
 for j:=1 to nombre_especes do  if (a[i-1,j-1]<>0) then begin
 if ((abs(abs(a[i-1,j-1])-1)>fracmax) and (a[i-1,j-1]>0)) then
 if s1<>'' then s1:=s1+' + '+floattostr(a[i-1,j-1])+' N( '+noms[j-1]+' )' else
 s1:=floattostr(a[i-1,j-1])+' N( '+noms[j-1]+' )';
 if ((abs(abs(a[i-1,j-1])-1)>fracmax) and (a[i-1,j-1]<0)) then
 if s1<>'' then s1:=s1+' - '+floattostr(-a[i-1,j-1])+' N( '+noms[j-1]+' )' else
 s1:='- '+floattostr(-a[i-1,j-1])+' N( '+noms[j-1]+' )';
 if (abs(a[i-1,j-1]-1)<fracmax) then
 if s1<>'' then s1:=s1+' + '+'N( '+noms[j-1]+' )' else
 s1:='N( '+noms[j-1]+' )';
 if (abs(a[i-1,j-1]+1)<fracmax) then
 if s1<>'' then s1:=s1+' - '+'N( '+noms[j-1]+' )' else
 s1:='-N( '+noms[j-1]+' )';
 end;
 if s1='' then s1:='0';
 s1:=s1+' = '+floattostr(bbb[i-1])+' mol';
 equations_conservation[i-1]:=s1;
 end;

setlength(aaa,rang,nombre_especes);
for i:=1 to rang do
for j:=1 to nombre_especes do
aaa[i-1,places_especes[j-1]-1]:=a[i-1,j-1];

setlength(coeff_stoechio,reac,nombre_especes);
 if reac>0 then for i:=1 to reac do
  for j:=1 to nombre_especes do
  coeff_stoechio[i-1,places_especes[j-1]-1]:=coefficients_stoechiometriques[i-1,j-1];

  setlength(deltarG0,reac);
   if reac>0 then for i:=1 to reac do begin
   deltarG0[i-1]:=0;
   for j:=1 to nombre_especes do
   deltarG0[i-1]:=
   deltarG0[i-1]+coeff_stoechio[i-1,j-1]*potentiel_standard[j-1];
   end;

   if reac>0 then for i:=1 to reac do
    reactions[i-1]:=reactions[i-1]+' log K='+floattostrf(
    -deltarG0[i-1]/temperature/constante_gaz_parfaits/ln(10),fffixed,
    3,6);



  finalize(places_especes); finalize(a);
 finalize(coefficients_stoechiometriques); finalize(noms);
 finalize(f_b);
end;


procedure DetermineReactions(aa:matricereelle;  bb:tableaureel;
nombre_especes,nombre_type_atomes_gj:longint;
noms_1,f_b_1:tableaustring;
var rang,reac:longint;
var reactions,equations_conservation,equations_avancements: tableaustring;
var aaa:matricereelle; var b:tableaureel;
var coeff_stoechio:matricereelle;
potentiel_standard:tableaureel;
var deltarG0,logk:tableaureel;
temperature:float);
var i,j,k:longint; trouve,coefentiers,reaction_ne_compte_pas,bon_facteur:boolean;
s1,s2:string;   fracmax,facteur,facteur_actuel,toto:float;
bbb:tableaureel;  a,coefficients_stoechiometriques:matricereelle;
places_especes:tableauentier; noms,f_b:tableaustring;
label 3012,3017,3052,444,1024;

begin
fracmax:=1e-10;
rang:=0;
 facteur:=1;
 setlength(a,nombre_type_atomes_gj,nombre_especes);
 setlength(bbb,nombre_especes);
 {a:=copy(aa);}
 for i:=1 to nombre_especes do
 for j:=1 to  nombre_type_atomes_gj do
 a[j-1,i-1]:=aa[j-1,i-1];
    {bbb:=copy(bb);}
    for i:=1 to  nombre_especes do bbb[i-1]:=bb[i-1];
 setlength(places_especes,nombre_especes);
 for i:=1 to nombre_especes do places_especes[i-1]:=i;

 setlength(noms,nombre_especes);
 for i:=1 to  nombre_especes do
 noms[i-1]:=noms_1[i-1];
 setlength(f_b,nombre_especes);
 for i:=1 to  nombre_especes do
 f_b[i-1]:=f_b_1[i-1];

 coefentiers:=true;
 for i:=1 to nombre_especes do
 for j:=1 to nombre_type_atomes_gj do
 coefentiers:=coefentiers and EstEntier(a[j-1,i-1],fracmax);


 for i:=1 to MinEntier(nombre_especes,nombre_type_atomes_gj) do begin
 verifiematricenulle(a,nombre_especes,nombre_type_atomes_gj);


  {cas ou le pivot est nul: on cherche quelles lignes et colonnes permuter}
  if (a[i-1,i-1]=0) then begin

    trouve:=false;


      if  ((i<=nombre_especes) and (i<nombre_type_atomes_gj)) then begin
    k:=i;
    for j:=i+1 to nombre_type_atomes_gj do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end; end;

     if  ((i<nombre_especes) and (i<=nombre_type_atomes_gj)) then begin
    j:=i;
    for k:=i+1 to nombre_especes do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end;     end;


        if  ((i<nombre_especes) and (i<nombre_type_atomes_gj)) then
    for k:=i+1 to nombre_especes do
    for j:=i+1 to nombre_type_atomes_gj do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end;

          if  ((i=nombre_especes) and (i=nombre_type_atomes_gj)) then goto 3012;


    if not(trouve) then goto 3012;
    1024: permutelignes(a,i,j,nombre_especes);
           permutecolonnes(a,i,k,nombre_type_atomes_gj);
  permutenoms(noms,i,k);
  permutenoms(f_b,i,k);
  permutereels(bbb,i,k);
  permuteentiers(places_especes,i,k);
  end; {du cas pivot nul}



  if a[i-1,i-1]=1 then inc(rang);
  if a[i-1,i-1]<>1 then begin
  if (coefentiers and (abs(a[i-1,i-1])>1)) then facteur:=facteur*abs(a[i-1,i-1]);
  multiplieligne(a,i,1/a[i-1,i-1],nombre_especes);
  inc(rang);
    end;

 if i>1 then for j:=1 to i-1 do
 if a[j-1,i-1]<>0 then
 ajouteligne(a,j,i,-a[j-1,i-1],nombre_especes);

  if i<nombre_type_atomes_gj then for j:=i+1 to nombre_type_atomes_gj do
 if a[j-1,i-1]<>0 then
 ajouteligne(a,j,i,-a[j-1,i-1],nombre_especes);
 end;
 3012:
  setlength(reactions,nombre_especes-rang);
  setlength(coefficients_stoechiometriques,
  nombre_especes-rang,nombre_especes);
  reac:=0;
  for i:=1 to nombre_especes-rang do begin
  reaction_ne_compte_pas:=true;
  for j:=1 to rang do reaction_ne_compte_pas:=
  reaction_ne_compte_pas and (a[j-1,rang+i-1]=0);
  if reaction_ne_compte_pas then goto 3017;
  inc(reac);
  facteur_actuel:=1;
  {recherche du facteur pour avoir des coef entiers}
  if facteur>1 then
  for k:=1 to round(facteur) do begin
  bon_facteur:=true;
  for j:=1 to rang do
  bon_facteur:=bon_facteur and
  EstEntier(k*a[j-1,rang+i-1],fracmax);
  if bon_facteur then begin
  facteur_actuel:=k;
  goto 3052;
  end;
  end;
  3052:
  for j:=1 to rang do begin
    coefficients_stoechiometriques[reac-1,j-1]:=-a[j-1,rang+i-1]*facteur_actuel;
if EstEntier(coefficients_stoechiometriques[reac-1,j-1],fracmax) then
coefficients_stoechiometriques[reac-1,j-1]:=
round(coefficients_stoechiometriques[reac-1,j-1]);
end;
   coefficients_stoechiometriques[reac-1,rang+i-1]:=facteur_actuel;
if EstEntier(coefficients_stoechiometriques[reac-1,rang+i-1],fracmax) then
coefficients_stoechiometriques[reac-1,rang+i-1]:=
round(coefficients_stoechiometriques[reac-1,rang+i-1]);
   3017:
   end;

   for i:=1 to reac do begin
   s1:=''; s2:='';
   for j:=1 to nombre_especes do begin
   if coefficients_stoechiometriques[i-1,j-1]<0 then
   if s1<>'' then
   if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then s1:=s1+' + '+floattostr(-coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
   s1:=s1+' + '+noms[j-1]
   else
   if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then
   s1:=floattostr(-coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
   s1:=noms[j-1];

   if coefficients_stoechiometriques[i-1,j-1]>0 then
   if s2<>'' then
    if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then
   s2:=s2+' + '+floattostr(coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
     s2:=s2+' + '+noms[j-1]
   else
    if (abs(abs(coefficients_stoechiometriques
   [i-1,j-1])-1)>fracmax) then
   s2:=floattostr(coefficients_stoechiometriques
   [i-1,j-1])+' '+noms[j-1] else
    s2:=noms[j-1] ;
   end;

   reactions[i-1]:=s1+' = '+s2;
   end;
    setlength(reactions,reac);

   setlength(b,rang);
   for i:=1 to rang do begin
    toto:=0;
    for j:=1 to nombre_especes do
    toto:=toto+a[i-1,j-1]*bbb[j-1];
    b[i-1]:=toto;
    end;


{recherche du facteur pour avoir des coef entiers}
  if facteur>1 then
  for j:=1 to rang do begin
    for k:=1 to round(facteur) do begin
  bon_facteur:=true;
  for i:=1 to nombre_especes do
  bon_facteur:=bon_facteur and
  EstEntier(k*a[j-1,i-1],fracmax);
  if bon_facteur then begin
   for i:=1 to nombre_especes do begin
   a[j-1,i-1]:=k*a[j-1,i-1];
 if EstEntier(a[j-1,i-1],fracmax) then
   a[j-1,i-1]:=round(a[j-1,i-1]);
   end;
   b[j-1]:=k*b[j-1];
   goto 444;
     end;             {du cas bon facteur}
      end;
      {de la boucle en k}
      444:
      end;{de la boucle en j}


       setlength(equations_conservation,rang);
 for i:=1 to rang do begin
 s1:='';
 for j:=1 to nombre_especes do  if (a[i-1,j-1]<>0) then begin
 if ((abs(abs(a[i-1,j-1])-1)>fracmax) and (a[i-1,j-1]>0)) then
 if s1<>'' then s1:=s1+' + '+floattostr(a[i-1,j-1])+' N( '+noms[j-1]+' )' else
 s1:=floattostr(a[i-1,j-1])+' N( '+noms[j-1]+' )';
 if ((abs(abs(a[i-1,j-1])-1)>fracmax) and (a[i-1,j-1]<0)) then
 if s1<>'' then s1:=s1+' - '+floattostr(-a[i-1,j-1])+' N( '+noms[j-1]+' )' else
 s1:='- '+floattostr(-a[i-1,j-1])+' N( '+noms[j-1]+' )';
 if (abs(a[i-1,j-1]-1)<fracmax) then
 if s1<>'' then s1:=s1+' + '+'N( '+noms[j-1]+' )' else
 s1:='N( '+noms[j-1]+' )';
 if (abs(a[i-1,j-1]+1)<fracmax) then
 if s1<>'' then s1:=s1+' - '+'N( '+noms[j-1]+' )' else
 s1:='-N( '+noms[j-1]+' )';
 end;
 if s1='' then s1:='0';
 s1:=s1+' = '+floattostr(b[i-1])+' mol';
 equations_conservation[i-1]:=s1;
 end;

setlength(equations_avancements,nombre_especes);
for i:=1 to nombre_especes do begin
s1:='N( '+noms[i-1]+' ) = ';
if bbb[i-1]<>0 then s1:=s1+floattostr(bbb[i-1])+' mol ';
if reac>0 then
for j:=1 to reac do
if  coefficients_stoechiometriques[j-1,i-1]<>0 then  begin
if ((abs(abs(coefficients_stoechiometriques[j-1,i-1])-1)>fracmax)
and (coefficients_stoechiometriques[j-1,i-1]>0)) then
s1:=s1+'+ '+floattostr(coefficients_stoechiometriques[j-1,i-1])+' X'+inttostr(j);
if ((abs(abs(coefficients_stoechiometriques[j-1,i-1])-1)>fracmax)
and (coefficients_stoechiometriques[j-1,i-1]<0)) then
s1:=s1+' '+floattostr(coefficients_stoechiometriques[j-1,i-1])+' X'+inttostr(j);
if ((abs(abs(coefficients_stoechiometriques[j-1,i-1])-1)<fracmax)
and (coefficients_stoechiometriques[j-1,i-1]<0)) then
s1:=s1+' -X'+inttostr(j);
if ((abs(abs(coefficients_stoechiometriques[j-1,i-1])-1)<fracmax)
and (coefficients_stoechiometriques[j-1,i-1]>0)) then
s1:=s1+' +X'+inttostr(j);
end;
if copy(s1,length(s1)-1,2)='= ' then s1:=s1+'0 mol';
equations_avancements[i-1]:=s1;
end;

setlength(aaa,rang,nombre_especes);
for i:=1 to rang do
for j:=1 to nombre_especes do
aaa[i-1,places_especes[j-1]-1]:=a[i-1,j-1];

setlength(coeff_stoechio,reac,nombre_especes);
 if reac>0 then for i:=1 to reac do
  for j:=1 to nombre_especes do
  coeff_stoechio[i-1,places_especes[j-1]-1]:=coefficients_stoechiometriques[i-1,j-1];

  setlength(deltarG0,reac);
   if reac>0 then for i:=1 to reac do begin
   deltarG0[i-1]:=0;
   for j:=1 to nombre_especes do
   deltarG0[i-1]:=
   deltarG0[i-1]+coeff_stoechio[i-1,j-1]*potentiel_standard[j-1];
   end;

    setlength(logk,reac);
     if reac>0 then for i:=1 to reac do
    logk[i-1]:=
    -deltarG0[i-1]/temperature/constante_gaz_parfaits/ln(10);




 finalize(bbb); finalize(places_especes); finalize(a);
 finalize(coefficients_stoechiometriques); finalize(noms);
 finalize(f_b);
end;


procedure DetermineMu0(coefficient_stoechiometriques:matricereelle;
logk:tableaureel; var mu0:tableaureel; nombre_especes,nombre_reactions:
integer; temperature:float);
var i,j,k:longint; trouve,coefentiers,reaction_ne_compte_pas:boolean;
s1,s2:string;   fracmax,toto:float;
 a:matricereelle;
places_especes:tableauentier;
label 3012,1024;

begin
fracmax:=1e-10;


 setlength(a,nombre_reactions,nombre_especes+1);
 for j:=1 to  nombre_reactions do begin
 for i:=1 to nombre_especes do
  a[j-1,i-1]:=coefficient_stoechiometriques[j-1,i-1];
 a[j-1,nombre_especes]:= constante_gaz_parfaits*temperature*logk[j-1]*ln(10);
 end;

 setlength(places_especes,nombre_especes);
 for i:=1 to nombre_especes do places_especes[i-1]:=i;


 coefentiers:=true;
 for i:=1 to nombre_especes do
 for j:=1 to nombre_reactions do
 coefentiers:=coefentiers and EstEntier(a[j-1,i-1],fracmax);


 for i:=1 to MinEntier(nombre_especes,nombre_reactions) do begin
 verifiematricenulle(a,nombre_especes,nombre_reactions);


  {cas ou le pivot est nul: on cherche quelles lignes et colonnes permuter}
  if (a[i-1,i-1]=0) then begin

    trouve:=false;


      if  ((i<=nombre_especes) and (i<nombre_reactions)) then begin
    k:=i;
    for j:=i+1 to nombre_reactions do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end; end;

     if  ((i<nombre_especes) and (i<=nombre_reactions)) then begin
    j:=i;
    for k:=i+1 to nombre_especes do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end;     end;


        if  ((i<nombre_especes) and (i<nombre_reactions)) then
    for k:=i+1 to nombre_especes do
    for j:=i+1 to nombre_reactions do
    if a[j-1,k-1]<>0 then  begin
    trouve:=true;
    goto 1024;
    end;

          if  ((i=nombre_especes) and (i=nombre_reactions)) then goto 3012;


    if not(trouve) then goto 3012;
    1024: permutelignes(a,i,j,nombre_especes+1);
           permutecolonnes(a,i,k,nombre_reactions);
  permuteentiers(places_especes,i,k);
  end; {du cas pivot nul}




  if a[i-1,i-1]<>1 then begin
  {if (coefentiers and (abs(a[i-1,i-1])>1)) then facteur:=facteur*abs(a[i-1,i-1]);}
  multiplieligne(a,i,1/a[i-1,i-1],nombre_especes+1);

    end;

 if i>1 then for j:=1 to i-1 do
 if a[j-1,i-1]<>0 then
 ajouteligne(a,j,i,-a[j-1,i-1],nombre_especes+1);

  if i<nombre_reactions then for j:=i+1 to nombre_reactions do
 if a[j-1,i-1]<>0 then
 ajouteligne(a,j,i,-a[j-1,i-1],nombre_especes+1);
 end;
 3012:





setlength(mu0,nombre_especes);

for j:=1 to nombre_reactions do
mu0[places_especes[j-1]-1]:=-a[j-1,nombre_especes];
if nombre_especes>nombre_reactions then
for j:=nombre_reactions+1 to nombre_especes do
mu0[places_especes[j-1]-1]:=0;


 finalize(places_especes); finalize(a);



end;
  end.


