Logo Search packages:      
Sourcecode: wims version File versions  Download package

chemeq.cc

#include "chemeq.h"
#include <math.h>
#include <strstream.h>
atome lesatomes[] ={
{-1, "e"},
{1, "H"},
{2, "He"},
{3, "Li"},
{4, "Be"},
{5, "B"},
{6, "C"},
{7, "N"},
{8, "O"},
{9, "F"},
{10, "Ne"},
{11, "Na"},
{12, "Mg"},
{13, "Al"},
{14, "Si"},
{15, "P"},
{16, "S"},
{17, "Cl"},
{18, "Ar"},
{19, "K"},
{20, "Ca"},
{21, "Sc"},
{22, "Ti"},
{23, "V"},
{24, "Cr"},
{25, "Mn"},
{26, "Fe"},
{27, "Co"},
{28, "Ni"},
{29, "Cu"},
{30, "Zn"},
{31, "Ga"},
{32, "Ge"},
{33, "As"},
{34, "Se"},
{35, "Br"},
{36, "Kr"},
{37, "Rb"},
{38, "Sr"},
{39, "Y"},
{40, "Zr"},
{41, "Nb"},
{42, "Mo"},
{43, "Tc"},
{44, "Ru"},
{45, "Rh"},
{46, "Pd"},
{47, "Ag"},
{48, "Cd"},
{49, "In"},
{50, "Sn"},
{51, "Sb"},
{52, "Te"},
{53, "I"},
{54, "Xe"},
{55, "Cs"},
{56, "Ba"},
{57, "La"},
{58, "Ce"},
{59, "Pr"},
{60, "Nd"},
{61, "Pm"},
{62, "Sm"},
{63, "Eu"},
{64, "Gd"},
{65, "Tb"},
{66, "Dy"},
{67, "Ho"},
{68, "Er"},
{69, "Tm"},
{70, "Yb"},
{71, "Lu"},
{72, "Hf"},
{73, "Ta"},
{74, "W"},
{75, "Re"},
{76, "Os"},
{77, "Ir"},
{78, "Pt"},
{79, "Au"},
{80, "Hg"},
{81, "Tl"},
{82, "Pb"},
{83, "Bi"},
{84, "Po"},
{85, "At"},
{86, "Rn"},
{87, "Fr"},
{88, "Ra"},
{89, "Ac"},
{90, "Th"},
{91, "Pa"},
{92, "U"},
{93, "Np"},
{94, "Pu"},
{95, "Am"},
{96, "Cm"},
{97, "Bk"},
{98, "Cf"},
{99, "Es"},
{100, "Fm"},
{101, "Md"},
{102, "No"},
{103, "Lr"},
{104, "Rf"},
{105, "Db"},
{106, "Sg"},
{107, "Bh"},
{108, "Hs"},
{109, "Mt"},
{110, "Uun"},
{111, "Uuu"},
{112, "Uub"},
{113, "Uut"},
{114, "Uuq"},
{115, "Uup"},
{116, "Uuh"},
{117, "Uus"},
{118, "Uuo"},
{0,"fin"}
};

ostream & Compteur::operator << (ostream & o)const{
  const_iterator i=begin(); 
  while (i != end()){
    o << i->first << " : " << i->second;
    if (++i != end()) o << " ";
  }
  return o;
}

ostream & operator << (ostream & o, const Compteur & c){
  return c.operator << (o);
}


void AtomeListe::compte(Compteur &c, fraction mult)const{
  const AtomeListe * al;
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
    string key(symb);
    c[key] +=1.0*nb*mult.i/mult.d;
  }
  else if (Zed==0){ /* cas d'un groupe */
    if (group) group->compte(c,mult*nb);
  }
  if (suiv) suiv->compte(c,mult);
};

void AtomeListe::numerote(int n=0){
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
    no = n;
  }
  else if (Zed==0){ /* cas d'un groupe */
    no = n;
    if (group) group->numerote();
  }
  if (suiv) suiv->numerote(n+1);
}

AtomeListe * AtomeListe::triage(AtomeListe * al){
  AtomeListe * al1;
  if(al->Z()!=0){ /* cas où ce n'est pas un groupe */
    if (al->suiv){
      al->suiv = triage(al->suiv);
    }
    while (al->suiv && al->suiv->Zed!=0 && 
         strcmp(al->symbole(), al->suiv->symbole()) > 1){
      al1=al; al=al->suiv; al1->suiv=al->suiv; al->suiv=triage(al1);
    }
  }
  else{ /* cas d'un groupe */
     if (al->groupe()) al->groupe(triage(al->groupe()));
  }
  return al;
}

void AtomeListe::printnorm(ostream & o){
  if (sqbr) o << "[";
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
    o << symb;
    if (nb!=1) o << nb;
  }
  else{ /* cas d'un groupe */
    o << "(";
    if (group) group->printnorm(o);
    o << ")" << nb;
  }  
  if (suiv) suiv->printnorm(o);
  if (sqbr) o << "]";
}

ostream & operator << (ostream & o, const AtomeListe & l){
  int n;
  const AtomeListe * al;
  if (l.sq()) o << "[";
  if(l.Z()>0 || l.Z()<-1){
    o << l.symbole();
  }
  else if (l.Z()==-1){ // cas de l'électron
    o << "e";
  }
  else{                // cas des groupes parenthésés
    o << "(";
    if((al=l.groupe())) o << *al;
    o << ")";
  }
  if((n=l.getmolecularite())>1) o << "_{" << n << "}";
  if((al=l.suivant())) o << *al;
  if (l.sq()) o << "]";
  return o;
}

char* moltypeStr[] = { "aq", "g", "s" };

const string Molec::signature()const{
  ostrstream o;
  o << liste();
  if (charge()){
    o << "^{";
    if(fabs(1.0*charge())!=1) o << fabs(1.0*charge());
    if(charge()>0) o << "+}"; else o << "-}";
  }
  if (t != aqueous) o << moltypeStr[t];
  return string (o.str());
}

void Molec::printnorm(ostream & o){
  if (nb!=1) o << nb << " ";
  al-> printnorm(o);
  if (ch) {
    o << "^";
    if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
    if(ch>0) o << "+"; else o << "-";
  }
  if (!iswater()&&!iselectron()) o << "_" << moltypeStr[t];
}

void Molec::coeff( fraction f){
  nb.i *= f.i;
  nb.d *= f.d;
  nb.simplifie();
}

bool Molec::printNernst(ostream & o, char * prefix =""){
  switch(t){
  case sol : return 0;
  case aqueous :
    if (iswater() || iselectron()) return 0;
    o << prefix << "[" << *al;
    if (ch){
      o << "^{";
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
      if(ch>0) o << "+}"; else o << "-}";
    }
    if (t != aqueous) o << "_{" << moltypeStr[t] << "}";
    o  <<"]";
    if (nb!=1) {
      o << "^{"; 
      printNombre(o);
      o << "}";
    }
    return 1;
  case gas :
    o << prefix << "P_{" << *al << "}";
    if (nb!=1) {
      o << "^{"; 
      printNombre(o);
      o << "}";
    }
    return 1;
  }
}

bool Molec::iswater()const{
  if (t != aqueous) return 0;
  if (signature()==string("H_{2}O") || 
      signature()==string("OH_{2}")) return 1;
  else return 0;
}

bool Molec::iselectron()const{
  return (signature()==string("e^{-}"));
}

fraction Molec::nbelectron()const{
  if (iselectron()) return nb;
  else return fraction(0);
}

void Molec::printNombre(ostream & o)const{
  if (nb.d==1){
    o << nb.i << "\\,";
  }
  else {
    o << "\\frac{" << nb.i << "}{" << nb.d << "}\\,";
  }
}

ostream & operator << (ostream & o, const Molec & m){
  if (m.nombre() != 1) m.printNombre(o);
  o << m.liste();
  if (m.charge()){
    o << "^{";
    if(fabs(1.0*m.charge())!=1) o << fabs(1.0*m.charge());
    if(m.charge()>0) o << "+}"; else o << "-}";
  }
  if (m.typage() != aqueous) o << "_{" << moltypeStr[m.typage()] << "}";
  return o;
}

void Membre::compte(Compteur & c)const{
  for(int i =0; i < size(); i++){
    operator [] (i)->compte(c);
  }
}

void Membre::numerote(){
  for (int i=0; i < size(); i++){
    operator [](i)->numero(i);
    operator [](i)->liste().numerote();
  }
}

void Membre::triage(){
  int i,j;
  for (i=0; i < size(); i++){
    operator [](i)->triage();
  }
  for (i=0; i < size(); i++){
    for (j=i+1; j < size(); j++){
      if (operator [](i)->signature() > operator [](j)->signature()){
      Molec * m = operator [](i);
      operator [](i) = operator [](j);
      operator [](j) = m;
      }
    }
  }
}

void Membre::printnorm(ostream & o){
  for(int i=0; i < size(); i++){
    operator[](i)->printnorm(o);
    if (i < size()-1) o << " + ";
  }
}

void Membre::coeff( fraction f){
  for (int i=0; i<size(); i++) operator[](i)->coeff(f);
}

int Membre::printableNernst(){
  int result=0;
  for (int i=0; i<size(); i++) {
    if (operator[](i)->typage() != sol && 
      !operator[](i)->iswater() &&
      !operator[](i)->iselectron()) result =1;
  }  
  return result;
}

bool Membre::redox()const{
  for (int i=0; i<size(); i++){
    if ((*this)[i]->iselectron()) /* c'est un électron */ return 1;
  }
  return 0;
}

fraction  Membre::nbelectron()const{
  fraction result(0);

  for(int i = 0; i<size(); i++) result=result+(*this)[i]->nbelectron();
  return result;
}

void Membre::printNernst(ostream & o){
  bool printed = 0; 
  char * prefix="";
  for (int i=0; i<size(); i++) {
    if (i>0) prefix="\\,";
    if (operator[](i)->printNernst(o, prefix)){
      printed = 1; 
    }
  }
  if (!printed) o << "1";
}

ostream & operator << (ostream & o, const Membre & m){
  for(int i=0; i < m.size()-1; i++){
    o << *m[i] << "\\,+\\,";
  }
  o << *m[m.size()-1];
  return o;
}

void Chemeq::printnorm(ostream & o){
  gauche->printnorm(o);
  o << " -> ";
  droit->printnorm(o);
  if (val>=0){
    o << " (";
    if (cste!=string("")) o << cste << " = ";
    o << val;
    if (redox()) o << " V";
    o << ")";
  }
}

string Chemeq::equilibre(){
  ostrstream s;
  Compteur cpg, cpd;
  gauche->compte(cpg);
  droit->compte(cpd);
  if(cpg==cpd) s << "OK";
  else s << "ERROR " << cpg << " / " << cpd;
  return string(s.str());
}

void Chemeq::coeff1(){
  fraction mult = gauche->operator[](0)->nombre();
  mult.inverse();
  gauche->coeff(mult);
  droit->coeff(mult);
  if (!redox()){
    val = val*mult.i/mult.d;
  }
}

bool Chemeq::redox()const{
  return gauche->redox() || droit->redox();
}

void Chemeq::printNernst(ostream & o){
  Membre * ga, * dr;
  if (!redox()){
    if (gauche->printableNernst()){
      o << "\\frac{";
      droit->printNernst(o);
      o << "}{";
      gauche->printNernst(o);
      o << "}";
    }
    else {
      droit->printNernst(o);
    }
    if (val >=0) {
      o << "\\,=\\,";
      if (cste!=string("")) o << cste << "\\,=\\,";
      o << val;
    }
    else{
      o << "\\,=\\,K";
    }
  }
  else{ /* c'est une réaction redox */
    o << "E\\,=\\,";
    if (val >=0) {
      o << val;
    }
    else{
      o << "E_{0}";
    }
    o << "\\,+\\,\\frac{R\\,T}{";
    o << gauche->nbelectron()+droit->nbelectron() << "\\,F}";
    o << "\\log";
    if (gauche->redox()){ /* c'est une réduction */
      ga=gauche; dr=droit;
    }
    else{ /* c'est une oxydation */
      ga=droit; dr=gauche;
    }
    if (dr->printableNernst()){
      o << "\\frac{";
      ga->printNernst(o);
      o << "}{";
      dr->printNernst(o);
      o << "}";
      }
      else {
      o << "(";
      ga->printNernst(o);
      o << ")";
      }
  }
}

ostream & operator << (ostream & o, const Chemeq & c){
  o << *c.membregauche() << "\\,\\rightarrow\\," << *c.membredroit();
  if (c.valeur() >=0) {
    o << "\\,(";
    if (c.constante()!=string("")) o << c.constante() << "\\,=\\,";
    o << c.valeur();
    if (c.redox()) o << " V";
    o << ")";
  }
  return o;
}

ostream & operator << (ostream & o, fraction f){
  o << f.i;
  if (f.d!=1) o << '/' << f.d;
  return o;
}

fraction operator * (fraction f, int m){
  fraction result = fraction(f.i*m, f.d);
  result.simplifie();
  return result;
}

fraction operator * (int m, fraction f){
  fraction result = fraction(f.i*m, f.d);
  result.simplifie();
  return result;
}

fraction operator * (fraction f, fraction m)
{
  fraction result = fraction(f.i*m.i, f.d*m.d);
  result.simplifie();
  return result;
}

fraction operator + (fraction f, fraction g){
  fraction result = fraction(f.i*g.d+g.i*f.d, f.d*g.d);
  result.simplifie();
  return result;
}

void fraction::simplifie(){
  int maxprem = 23;
  int premiers[]={2,3,5,7,11,13,17,19,23,29};
  int n;

  for (n=0; premiers[n]<= maxprem; n++){
    while (i % premiers[n] == 0 && d % premiers[n] == 0){
      i /= premiers[n]; d /= premiers[n];
    }
  }
}

bool operator > (fraction f, int i){
  return f.i > f.d*i;
}

bool operator != (fraction f, int i){
  return f.i != f.d*i;
}


Generated by  Doxygen 1.6.0   Back to index