Back to index

wims  3.65+svn20090927
chemeq.cc
Go to the documentation of this file.
00001 // -*- coding: utf-8 -*-
00002 #include "chemeq.h"
00003 #include <cmath>
00004 #include <cstdlib>
00005 
00006 atome lesatomes[] ={
00007 {-1, "e"},
00008 {1, "H"},
00009 {2, "He"},
00010 {3, "Li"},
00011 {4, "Be"},
00012 {5, "B"},
00013 {6, "C"},
00014 {7, "N"},
00015 {8, "O"},
00016 {9, "F"},
00017 {10, "Ne"},
00018 {11, "Na"},
00019 {12, "Mg"},
00020 {13, "Al"},
00021 {14, "Si"},
00022 {15, "P"},
00023 {16, "S"},
00024 {17, "Cl"},
00025 {18, "Ar"},
00026 {19, "K"},
00027 {20, "Ca"},
00028 {21, "Sc"},
00029 {22, "Ti"},
00030 {23, "V"},
00031 {24, "Cr"},
00032 {25, "Mn"},
00033 {26, "Fe"},
00034 {27, "Co"},
00035 {28, "Ni"},
00036 {29, "Cu"},
00037 {30, "Zn"},
00038 {31, "Ga"},
00039 {32, "Ge"},
00040 {33, "As"},
00041 {34, "Se"},
00042 {35, "Br"},
00043 {36, "Kr"},
00044 {37, "Rb"},
00045 {38, "Sr"},
00046 {39, "Y"},
00047 {40, "Zr"},
00048 {41, "Nb"},
00049 {42, "Mo"},
00050 {43, "Tc"},
00051 {44, "Ru"},
00052 {45, "Rh"},
00053 {46, "Pd"},
00054 {47, "Ag"},
00055 {48, "Cd"},
00056 {49, "In"},
00057 {50, "Sn"},
00058 {51, "Sb"},
00059 {52, "Te"},
00060 {53, "I"},
00061 {54, "Xe"},
00062 {55, "Cs"},
00063 {56, "Ba"},
00064 {57, "La"},
00065 {58, "Ce"},
00066 {59, "Pr"},
00067 {60, "Nd"},
00068 {61, "Pm"},
00069 {62, "Sm"},
00070 {63, "Eu"},
00071 {64, "Gd"},
00072 {65, "Tb"},
00073 {66, "Dy"},
00074 {67, "Ho"},
00075 {68, "Er"},
00076 {69, "Tm"},
00077 {70, "Yb"},
00078 {71, "Lu"},
00079 {72, "Hf"},
00080 {73, "Ta"},
00081 {74, "W"},
00082 {75, "Re"},
00083 {76, "Os"},
00084 {77, "Ir"},
00085 {78, "Pt"},
00086 {79, "Au"},
00087 {80, "Hg"},
00088 {81, "Tl"},
00089 {82, "Pb"},
00090 {83, "Bi"},
00091 {84, "Po"},
00092 {85, "At"},
00093 {86, "Rn"},
00094 {87, "Fr"},
00095 {88, "Ra"},
00096 {89, "Ac"},
00097 {90, "Th"},
00098 {91, "Pa"},
00099 {92, "U"},
00100 {93, "Np"},
00101 {94, "Pu"},
00102 {95, "Am"},
00103 {96, "Cm"},
00104 {97, "Bk"},
00105 {98, "Cf"},
00106 {99, "Es"},
00107 {100, "Fm"},
00108 {101, "Md"},
00109 {102, "No"},
00110 {103, "Lr"},
00111 {104, "Rf"},
00112 {105, "Db"},
00113 {106, "Sg"},
00114 {107, "Bh"},
00115 {108, "Hs"},
00116 {109, "Mt"},
00117 {110, "Uun"},
00118 {111, "Uuu"},
00119 {112, "Uub"},
00120 {113, "Uut"},
00121 {114, "Uuq"},
00122 {115, "Uup"},
00123 {116, "Uuh"},
00124 {117, "Uus"},
00125 {118, "Uuo"},
00126 {0,"fin"}
00127 };
00128 
00129 std::ostream & Compteur::operator << (std::ostream & o)const{
00130   const_iterator i=begin(); 
00131   while (i != end()){
00132     o << i->first << " : " << i->second;
00133     if (++i != end()) o << " ";
00134   }
00135   return o;
00136 }
00137 
00138 std::ostream & operator << (std::ostream & o, const Compteur & c){
00139   return c.operator << (o);
00140 }
00141 
00142 double AtomeListe::weight(fraction mult)const{
00143   const AtomeListe * al;
00144   double w=0.0;
00145   if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
00146     w=mendelweight(symb)*nb*mult.i/mult.d;
00147   }
00148   else if (Zed==0){ /* cas d'un groupe */
00149     if (group) w+=group->weight(mult*nb);
00150   }
00151   if (suiv) w+=suiv->weight(mult);
00152   return w;
00153 }
00154 
00155 void AtomeListe::compte(Compteur &c, fraction mult)const{
00156   const AtomeListe * al;
00157   if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
00158     std::string key(symb);
00159     c[key] +=1.0*nb*mult.i/mult.d;
00160   }
00161   else if (Zed==0){ /* cas d'un groupe */
00162     if (group) group->compte(c,mult*nb);
00163   }
00164   if (suiv) suiv->compte(c,mult);
00165 }
00166 
00167 void AtomeListe::numerote(int n){
00168   if(Zed!=0){ /* cas où ce n'est pas un groupe */
00169     no = n;
00170   }
00171   else if (Zed==0){ /* cas d'un groupe */
00172     no = n;
00173     if (group) group->numerote();
00174   }
00175   if (suiv) suiv->numerote(n+1);
00176 }
00177 
00178 AtomeListe * AtomeListe::triage(AtomeListe * al){
00179   AtomeListe * al1;
00180   if(al->Z()!=0){ /* cas où ce n'est pas un groupe */
00181     if (al->suiv){
00182       al->suiv = triage(al->suiv);
00183     }
00184     while (al->suiv && al->suiv->Zed!=0 && 
00185           strcmp(al->symbole(), al->suiv->symbole()) > 1){
00186       al1=al; al=al->suiv; al1->suiv=al->suiv; al->suiv=triage(al1);
00187     }
00188   }
00189   else{ /* cas d'un groupe */
00190      if (al->groupe()) al->groupe(triage(al->groupe()));
00191   }
00192   return al;
00193 }
00194 
00195 bool AtomeListe::isEqual(const AtomeListe & a2) const {
00196   std::stringstream s1, s2;
00197   printnorm(s1);
00198   a2.printnorm(s2);
00199   return s1.str() == s2.str();
00200 }
00201 
00202 void AtomeListe::printcount(std::ostream & o, const fraction& n, int multiple=1) const{
00203   if(Zed!=0){ /* cas où ce n'est pas un groupe */
00204     o << symb;
00205     o << ':' << n << '*' << multiple*nb;
00206   }
00207   else{ /* cas d'un groupe */
00208     if (group) group->printcount(o,n,nb);
00209   }  
00210   if (suiv) {o << ' '; suiv->printcount(o,n,multiple);}
00211 }
00212 
00213 void AtomeListe::printnorm(std::ostream & o) const{
00214   if (sqbr) o << "[";
00215   if(Zed!=0){ /* cas où ce n'est pas un groupe */
00216     o << symb;
00217     if (nb!=1) o << nb;
00218   }
00219   else{ /* cas d'un groupe */
00220     o << "(";
00221     if (group) group->printnorm(o);
00222     o << ")" << nb;
00223   }  
00224   if (suiv) suiv->printnorm(o);
00225   if (sqbr) o << "]";
00226 }
00227 
00228 std::ostream & operator << (std::ostream & o, const AtomeListe & l){
00229   int n;
00230   const AtomeListe * al;
00231   if (l.sq()) o << "[";
00232   if(l.Z()>0 || l.Z()<-1){
00233     o << l.symbole();
00234   }
00235   else if (l.Z()==-1){ // cas de l'électron
00236     o << "e";
00237   }
00238   else{                // cas des groupes parenthésés
00239     o << "(";
00240     if((al=l.groupe())) o << *al;
00241     o << ")";
00242   }
00243   if((n=l.getmolecularite())>1) o << "_{" << n << "}";
00244   if((al=l.suivant())) o << *al;
00245   if (l.sq()) o << "]";
00246   return o;
00247 }
00248 
00249 const char* moltypeStr[] = { "aq", "g", "s" };
00250 
00251 const std::string Molec::signature()const{
00252   std::ostringstream o;
00253   o << liste();
00254   if (charge()){
00255     o << "^{";
00256     if(fabs(1.0*charge())!=1) o << fabs(1.0*charge());
00257     if(charge()>0) o << "+}"; else o << "-}";
00258   }
00259   if (t != aqueous) o << moltypeStr[t];
00260   return std::string (o.str());
00261 }
00262 
00263 bool Molec::printcount(std::ostream & o, bool first) const{
00264   if (!first) o << ", ";
00265   first=false;
00266   printnorm(o);
00267   o << '|';
00268   al-> printcount(o,nb);
00269   return first;
00270 }
00271 
00272 bool Molec::printelec(std::ostream & o, bool first) const{
00273   if (!first) o << ", ";
00274   first=false;
00275   printnorm(o);
00276   o << '|';
00277   o << nb << '*' << ch;
00278   return first;
00279 }
00280 
00281 bool Molec::printspecies(std::ostream & o, bool first) const{
00282   if (!first) o << ", ";
00283   first=false;
00284   printnorm(o);
00285   return first;
00286 }
00287 
00288 void Molec::printnorm(std::ostream & o)const{
00289   if (nb!=1) o << nb << " ";
00290   al-> printnorm(o);
00291   if (ch) {
00292     o << "^";
00293     if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
00294     if(ch>0) o << "+"; else o << "-";
00295   }
00296   if (!iswater()&&!iselectron()) o << "_" << moltypeStr[t];
00297 }
00298 
00299 void Molec::coeff( fraction f){
00300   nb.i *= f.i;
00301   nb.d *= f.d;
00302   nb.simplifie();
00303 }
00304 
00305 bool Molec::printNernst(std::ostream & o, const char * prefix){
00306   switch(t){
00307   case sol : return 0;
00308   case aqueous :
00309     if (iswater() || iselectron()) return 0;
00310     o << prefix << "[" << *al;
00311     if (ch){
00312       o << "^{";
00313       if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
00314       if(ch>0) o << "+}"; else o << "-}";
00315     }
00316     if (t != aqueous) o << "_{" << moltypeStr[t] << "}";
00317     o  <<"]";
00318     if (nb!=1) {
00319       o << "^{"; 
00320       printNombre(o);
00321       o << "}";
00322     }
00323     return 1;
00324   case gas :
00325     o << prefix << "P_{" << *al << "}";
00326     if (nb!=1) {
00327       o << "^{"; 
00328       printNombre(o);
00329       o << "}";
00330     }
00331     return 1;
00332   }
00333 }
00334 
00335 bool Molec::printNernstWIMS(std::ostream & o, bool wantedlatex){
00336   if (iswater() || iselectron()) {
00337     return false;
00338   }
00339   switch(t){
00340   case sol : {
00341     return false;
00342   }
00343   case aqueous :
00344     if(wantedlatex){
00345       o <<  "[" << *al;
00346     }else{
00347       o << "["; al->printnorm(o);
00348     }
00349     if (ch){
00350       if(wantedlatex){
00351        o << "^{";
00352       }else{
00353        o << "^";
00354       }
00355       if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
00356       if(wantedlatex){
00357        if(ch>0) o << "+}"; else o << "-}";
00358       }else{
00359        if(ch>0) o << "+"; else o << "-";
00360       }
00361     }
00362     o  <<"]";
00363     if (nb!=1) {
00364       if(wantedlatex){
00365        o << "^{";
00366        if (nb.d==1){
00367          o << nb.i ;
00368        }
00369        else {
00370          o << "\\frac{" << nb.i << "}{" << nb.d << "}";
00371        }
00372        o << "}";
00373       }else{
00374        o << "^" << nb; 
00375       }
00376     }
00377     return true;
00378   case gas :
00379     if(wantedlatex){
00380       o << "P_{" << *al << "}";
00381     }else{
00382       o << "P_"; al->printnorm(o);
00383     }
00384     if (nb!=1) {
00385       if(wantedlatex){
00386        o << "^{";
00387        if (nb.d==1){
00388          o << nb.i ;
00389        }
00390        else {
00391          o << "\\frac{" << nb.i << "}{" << nb.d << "}";
00392        }
00393        o << "}";
00394       }else{
00395        o << "^" << nb; 
00396       }
00397     }
00398     return true;
00399   }
00400   return false;
00401 }
00402 
00403 bool Molec::iswater()const{
00404   if (t != aqueous) return 0;
00405   if (signature()==std::string("H_{2}O") || 
00406       signature()==std::string("OH_{2}")) return 1;
00407   else return 0;
00408 }
00409 
00410 bool Molec::iselectron()const{
00411   return (signature()==std::string("e^{-}"));
00412 }
00413 
00414 fraction Molec::nbelectron()const{
00415   if (iselectron()) return nb;
00416   else return fraction(0);
00417 }
00418 
00419 void Molec::add(fraction f){
00420   nb = nb+f;
00421 }
00422 
00423 void Molec::sub(fraction f){
00424   nb = nb-f;
00425 }
00426 
00427 void Molec::printNombre(std::ostream & o)const{
00428   if (nb.d==1){
00429     o << nb.i << "\\,";
00430   }
00431   else {
00432     o << "\\frac{" << nb.i << "}{" << nb.d << "}\\,";
00433   }
00434 }
00435 
00436 std::ostream & operator << (std::ostream & o, const Molec & m){
00437   if (m.nombre() != 1) m.printNombre(o);
00438   o << m.liste();
00439   if (m.charge()){
00440     o << "^{";
00441     if(fabs(1.0*m.charge())!=1) o << fabs(1.0*m.charge());
00442     if(m.charge()>0) o << "+}"; else o << "-}";
00443   }
00444   if (m.typage() != aqueous) o << "_{" << moltypeStr[m.typage()] << "}";
00445   return o;
00446 }
00447 
00448 int Membre::findMol(const Molec * m){
00449   // returns the index of a molecule with the same atomlist if any
00450   // else returns -1.
00451   int result=-1;
00452   for(int i=0; i<size(); i++){
00453     if ((*this)[i]->eqMol(m)) result=i;
00454   }
00455   return result;
00456 }
00457 
00458 void Membre::addMol(const Molec * m){
00459   int i = findMol(m);
00460   if (i < 0){
00461     push_back(new Molec(*m));
00462   } else {
00463     (*this)[i]->add(m->nombre());
00464   }
00465 }
00466 
00467 void Membre::addMembre(const Membre * m){
00468   for(int i=0; i<m->size(); i++){
00469     addMol((*m)[i]);
00470   }
00471 }
00472 
00473 void Membre::eraseNull(){
00474   Membre m(*this);
00475   clear();
00476   for(int i=0; i < m.size();i++){
00477     if (m[i]->nombre().i>0) push_back(m[i]);
00478   }
00479 }
00480 
00481 void Membre::compte(Compteur & c)const{
00482   for(int i =0; i < size(); i++){
00483     operator [] (i)->compte(c);
00484   }
00485 }
00486 
00487 void Membre::numerote(){
00488   for (int i=0; i < size(); i++){
00489     operator [](i)->numero(i);
00490     operator [](i)->liste().numerote();
00491   }
00492 }
00493 
00494 void Membre::triage(){
00495   int i,j;
00496   for (i=0; i < size(); i++){
00497     operator [](i)->triage();
00498   }
00499   for (i=0; i < size(); i++){
00500     for (j=i+1; j < size(); j++){
00501       if (operator [](i)->signature() > operator [](j)->signature()){
00502        Molec * m = operator [](i);
00503        operator [](i) = operator [](j);
00504        operator [](j) = m;
00505       }
00506     }
00507   }
00508 }
00509 
00510 void Membre::printcount(std::ostream & o) const{
00511   bool first=true;
00512   for(int i=0; i < size(); i++){
00513     first=operator[](i)->printcount(o,first);
00514   }
00515 }
00516 
00517 void Membre::printelec(std::ostream & o) const{
00518   bool first=true;
00519   for(int i=0; i < size(); i++){
00520     first=operator[](i)->printelec(o,first);
00521   }
00522 }
00523 
00524 void Membre::printspecies(std::ostream & o) const{
00525   bool first=true;
00526   for(int i=0; i < size(); i++){
00527     first=operator[](i)->printspecies(o,first);
00528   }
00529 }
00530 
00531 void Membre::printnorm(std::ostream & o) const{
00532   for(int i=0; i < size(); i++){
00533     operator[](i)->printnorm(o);
00534     if (i < size()-1) o << " + ";
00535   }
00536 }
00537 
00538 void Membre::printweight(std::ostream & o) const{
00539   for(int i=0; i < size(); i++){
00540     o << operator[](i)->weight();
00541     if (i < size()-1) o << " ";
00542   }
00543 }
00544 
00545 void Membre::coeff( fraction f){
00546   for (int i=0; i<size(); i++) operator[](i)->coeff(f);
00547 }
00548 
00549 int Membre::printableNernst(){
00550   int result=0;
00551   for (int i=0; i<size(); i++) {
00552     if (operator[](i)->typage() != sol && 
00553        !operator[](i)->iswater() &&
00554        !operator[](i)->iselectron()) result =1;
00555   }  
00556   return result;
00557 }
00558 
00559 bool Membre::redox()const{
00560   for (int i=0; i<size(); i++){
00561     if ((*this)[i]->iselectron()) /* c'est un électron */ return 1;
00562   }
00563   return 0;
00564 }
00565 
00566 fraction  Membre::nbelectron()const{
00567   fraction result(0);
00568 
00569   for(int i = 0; i<size(); i++) result=result+(*this)[i]->nbelectron();
00570   return result;
00571 }
00572 
00573 void Membre::printNernst(std::ostream & o){
00574   bool printed = 0; 
00575   const char * prefix="";
00576   for (int i=0; i<size(); i++) {
00577     if (i>0) prefix="\\,";
00578     if (operator[](i)->printNernst(o, prefix)){
00579       printed = 1; 
00580     }
00581   }
00582   if (!printed) o << "1";
00583 }
00584 
00585 void Membre::printNernstWIMS(std::ostream & o, bool wantedlatex){
00586   bool printed = false; 
00587   bool addcomma = false;
00588   for (int i=0; i<size(); i++) {
00589     std::ostringstream w;
00590     if (operator[](i)->printNernstWIMS(w,wantedlatex)){
00591       if (addcomma) o << ", ";
00592       o << w.str();
00593       printed = true; 
00594       addcomma = true;
00595     } else {
00596       addcomma = false;
00597     }
00598   }
00599   if (!printed) o << "1";
00600 }
00601 
00602 std::ostream & operator << (std::ostream & o, const Membre & m){
00603   for(int i=0; i < m.size()-1; i++){
00604     o << *m[i] << "\\,+\\,";
00605   }
00606   o << *m[m.size()-1];
00607   return o;
00608 }
00609 
00610 Membre operator & (Membre & m1, Membre & m2){
00611   Membre result;
00612   //result.printnorm(std::cout);
00613   fraction min(1);
00614   for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
00615     for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
00616       if ((*i)->eqMol(*j)){
00617        Molec *m = new Molec(**i);
00618        if ((*i)->nb > (*j)->nb){
00619          min=(*j)->nb;
00620        }else{
00621          min=(*i)->nb;
00622        }
00623        m->nb=min;
00624        result.push_back(m);
00625       }
00626     }
00627   }
00628   return result;
00629 }
00630 
00631 Membre operator - (Membre & m1, Membre & m2){
00632   Membre result;
00633   fraction diff(1);
00634   for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
00635     Molec *m = new Molec(**i);
00636     for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
00637       if ((*i)->eqMol(*j)){
00638        diff=(*i)->nb - (*j)->nb;
00639        m->nb=diff;
00640       }
00641     }
00642     result.push_back(m);
00643   }
00644   return result;
00645 }
00646 
00647 bool Chemeq::valdefined()const{
00648   return val > MINVAL;
00649 }
00650 
00651 void Chemeq::addChemeq(const Chemeq * c){
00652   if (valdefined() && c->valdefined()){
00653     long double e1=enthalpy(), e2=c->enthalpy();
00654     fraction n1=nbelectron(), n2=c->nbelectron();
00655     long double e = e1+e2;
00656     fraction n=n1+n2;
00657     if (n.i==0) val=exp(-e/R/T0);
00658     else val=-e*n.d/n.i/Faraday;
00659   } else {
00660     val=MINVAL;
00661   }
00662   gauche->addMembre(c->gauche);
00663   droit->addMembre(c->droit);
00664   simplifie(true);
00665 }
00666 
00667 void Chemeq::subChemeq(const Chemeq * c){
00668   if (valdefined() && c->valdefined()){
00669     long double e1=enthalpy(), e2=c->enthalpy();
00670     fraction n1=nbelectron(), n2=c->nbelectron();
00671     long double e = e1-e2;
00672     fraction n=n1-n2;
00673     if (n.i==0) {
00674     val=exp(-e/R/T0);
00675     } else{
00676       val=-e*n.d/n.i/Faraday;
00677     }
00678   } else {
00679     val=MINVAL;
00680   }
00681   gauche->addMembre(c->droit);
00682   droit->addMembre(c->gauche);
00683   simplifie(true);
00684 }
00685 
00686 long double Chemeq::enthalpy() const{
00687   fraction n=nbelectron();
00688   if (redox()){
00689     return -val*n.i/n.d*Faraday;
00690   } else {
00691     return -R*T0*log(val);
00692   }
00693 }
00694 
00695 void Chemeq::simplifie(bool tri=false){
00696   Membre communs(*gauche & *droit);
00697   if (communs.size()>0){
00698     Membre * g, *d;
00699     g= new Membre(*gauche - communs);
00700     d= new Membre(*droit  - communs);
00701     delete gauche;
00702     delete droit;
00703     gauche=g;
00704     droit =d;
00705   }
00706   gauche->eraseNull();
00707   droit->eraseNull();
00708   if (tri){
00709     numerote(); 
00710     triage();
00711   }
00712 }
00713 
00714 void Chemeq::printnorm(std::ostream & o){
00715   gauche->printnorm(o);
00716   o << " -> ";
00717   droit->printnorm(o);
00718   if (val>MINVAL){
00719     o << " (";
00720     if (cste!=std::string("")) o << cste << " = ";
00721     o << val;
00722     if (redox()) o << " V";
00723     o << ")";
00724   }
00725 }
00726 
00727 void Chemeq::printcount(std::ostream & o) const {
00728   gauche->printcount(o);
00729   o << "; ";
00730   droit->printcount(o);
00731 }
00732 
00733 void Chemeq::printelec(std::ostream & o) const {
00734   gauche->printelec(o);
00735   o << "; ";
00736   droit->printelec(o);
00737 }
00738 
00739 void Chemeq::printspecies(std::ostream & o) const {
00740   gauche->printspecies(o);
00741   o << "; ";
00742   droit->printspecies(o);
00743 }
00744 
00745 void Chemeq::printweight(std::ostream & o) const{
00746   gauche->printweight(o);
00747   o << " ";
00748   droit->printweight(o);
00749 }
00750 
00751 std::string Chemeq::equilibre(){
00752   std::ostringstream s;
00753   Compteur cpg, cpd;
00754   gauche->compte(cpg);
00755   droit->compte(cpd);
00756   if(cpg==cpd) s << "OK";
00757   else s << "ERROR " << cpg << " / " << cpd;
00758   return std::string(s.str());
00759 }
00760 
00761 void Chemeq::coeff1(){
00762   fraction mult = gauche->operator[](0)->nombre();
00763   mult.inverse();
00764   gauche->coeff(mult);
00765   droit->coeff(mult);
00766   simplifie();
00767   if (!redox() && valdefined()){
00768     val = val*mult.i/mult.d;
00769   }
00770 }
00771 
00772 void Chemeq::multiply(int num, int den){
00773   fraction mult(num,den);
00774   gauche->coeff(mult);
00775   droit->coeff(mult);
00776   simplifie();
00777   if (!redox() && valdefined()){
00778     val = val*mult.i/mult.d;
00779   }
00780 }
00781 
00782 bool Chemeq::redox()const{
00783   return gauche->redox() || droit->redox();
00784 }
00785 
00786 void Chemeq::printNernst(std::ostream & o, 
00787                       std::ostream & w, 
00788                       bool wantedlatex){
00789   Membre * ga, * dr;
00790   if (!redox()){
00791     if (gauche->printableNernst()){
00792       o << "\\frac{";
00793       droit->printNernst(o);
00794       o << "}{";
00795       gauche->printNernst(o);
00796       o << "}";
00797     }
00798     else {
00799       droit->printNernst(o);
00800     }
00801     droit->printNernstWIMS(w,wantedlatex);
00802     w << "; ";
00803     gauche->printNernstWIMS(w,wantedlatex);
00804     if (val > MINVAL) {
00805       o << "\\,=\\,";
00806       if (cste!=std::string("")) o << cste << "\\,=\\,";
00807       o << valeur_latex();
00808       if(wantedlatex){
00809        w << "; " << valeur_latex();
00810       }else{
00811        w << "; " << val;
00812       }
00813     }
00814     else{
00815       o << "\\,=\\,K";
00816       w << "; K";
00817     }
00818   }
00819   else{ /* c'est une réaction redox  */
00820     o << "E\\,=\\,";
00821     if(wantedlatex){
00822       w << "E\\,=\\,";
00823     }else{
00824       w << "E=";
00825     }
00826     if (val > MINVAL) {
00827       o << val;
00828       w << val << ";";
00829     }
00830     else{
00831       o << "E_{0}";
00832       if(wantedlatex){
00833        w << "E_{0};";
00834       }else{
00835        w << "E0;";
00836       }
00837     }
00838     o << "\\,+\\,\\frac{R\\,T}{";
00839     o << gauche->nbelectron()+droit->nbelectron() << "\\,F}";
00840     o << "\\log";
00841     w << gauche->nbelectron()+droit->nbelectron() << ";";
00842     if (gauche->redox()){ /* c'est une réduction */
00843       ga=gauche; dr=droit;
00844     }
00845     else{ /* c'est une oxydation */
00846       ga=droit; dr=gauche;
00847     }
00848     if (dr->printableNernst()){
00849       o << "\\frac{";
00850       ga->printNernst(o);
00851       o << "}{";
00852       dr->printNernst(o);
00853       o << "}";
00854     }
00855     else {
00856       o << "(";
00857       ga->printNernst(o);
00858       o << ")";
00859     }
00860     // implanter la sortie pour Wims ici.
00861     dr->printNernstWIMS(w,wantedlatex);
00862     w << "; ";
00863     ga->printNernstWIMS(w,wantedlatex);
00864   }
00865 }
00866 
00867 std::string Chemeq::valeur_latex()const{
00868   std::ostringstream so;
00869   so << val;
00870   std::string s(so.str());
00871   std::string::size_type epos=s.find('e',0);
00872   if (epos!=std::string::npos){
00873     s.erase(epos,1);
00874     s.insert(epos,"\\times 10^{");
00875     s=s+"}";
00876   }
00877   return (std::string) s;
00878 }
00879 
00880 std::ostream & operator << (std::ostream & o, const Chemeq & c){
00881   o << *c.membregauche() << "\\,\\rightarrow\\," << *c.membredroit();
00882   if (c.valeur() > MINVAL) {
00883     o << "\\,(";
00884     if (c.constante()!=std::string("")) o << c.constante() << "\\,=\\,";
00885     o << c.valeur_latex();
00886     if (c.redox()) o << " V";
00887     o << ")";
00888   }
00889   return o;
00890 }
00891 
00892 std::ostream & operator << (std::ostream & o, fraction f){
00893   o << f.i;
00894   if (f.d!=1) o << '/' << f.d;
00895   return o;
00896 }
00897 
00898 fraction operator * (fraction f, int m){
00899   fraction result = fraction(f.i*m, f.d);
00900   result.simplifie();
00901   return result;
00902 }
00903 
00904 fraction operator * (int m, fraction f){
00905   fraction result = fraction(f.i*m, f.d);
00906   result.simplifie();
00907   return result;
00908 }
00909 
00910 fraction operator * (fraction f, fraction m)
00911 {
00912   fraction result = fraction(f.i*m.i, f.d*m.d);
00913   result.simplifie();
00914   return result;
00915 }
00916 
00917 fraction operator + (fraction f, fraction g){
00918   fraction result = fraction(f.i*g.d+g.i*f.d, f.d*g.d);
00919   result.simplifie();
00920   return result;
00921 }
00922 
00923 fraction operator - (fraction f, fraction g){
00924   fraction result = fraction(f.i*g.d-g.i*f.d, f.d*g.d);
00925   result.simplifie();
00926   return result;
00927 }
00928 
00929 const fraction & minFraction(const fraction& f1, const fraction &f2){
00930   if (f1.i*f2.d > f2.i*f1.d) return f1;
00931   else return f2;
00932 }
00933 
00934 void fraction::simplifie(){
00935   int maxprem = 23;
00936   int premiers[]={2,3,5,7,11,13,17,19,23,29};
00937   int n;
00938 
00939   for (n=0; premiers[n]<= maxprem; n++){
00940     while (i % premiers[n] == 0 && d % premiers[n] == 0){
00941       i /= premiers[n]; d /= premiers[n];
00942     }
00943   }
00944 }
00945 
00946 bool operator > (fraction f, int i){
00947   return f.i > f.d*i;
00948 }
00949 
00950 bool operator > (fraction f1, fraction f2){
00951   return f1.i*f2.d > f1.d*f2.i;
00952 }
00953 
00954 bool operator != (fraction f, int i){
00955   return f.i != f.d*i;
00956 }
00957 
00958 double mendelweight(int i){
00959   if (i>=0) return strtod (table[i].info[WEIGHT],0); else return 0.0;
00960 }
00961 
00962 int findmendel(const char * symb){
00963   int i=0;
00964   while (table[i].info[0] && strcmp(table[i].info[SYMBOL], symb) != 0) i++;
00965   if (table[i].info[0]) return i; else return -1;
00966 }
00967 
00968 double mendelweight(const char * symb){
00969   int i;
00970   i = findmendel(symb);
00971   return mendelweight(i);
00972 }