Subversion Repositories wimsdev

Rev

Rev 6872 | Rev 12963 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
104 bpr 1
// -*- coding: utf-8 -*-
10 reyssat 2
#include "chemeq.h"
472 georgesk 3
#include <cmath>
4
#include <cstdlib>
10 reyssat 5
 
6
atome lesatomes[] ={
7
{-1, "e"},
8
{1, "H"},
9
{2, "He"},
10
{3, "Li"},
11
{4, "Be"},
12
{5, "B"},
13
{6, "C"},
14
{7, "N"},
15
{8, "O"},
16
{9, "F"},
17
{10, "Ne"},
18
{11, "Na"},
19
{12, "Mg"},
20
{13, "Al"},
21
{14, "Si"},
22
{15, "P"},
23
{16, "S"},
24
{17, "Cl"},
25
{18, "Ar"},
26
{19, "K"},
27
{20, "Ca"},
28
{21, "Sc"},
29
{22, "Ti"},
30
{23, "V"},
31
{24, "Cr"},
32
{25, "Mn"},
33
{26, "Fe"},
34
{27, "Co"},
35
{28, "Ni"},
36
{29, "Cu"},
37
{30, "Zn"},
38
{31, "Ga"},
39
{32, "Ge"},
40
{33, "As"},
41
{34, "Se"},
42
{35, "Br"},
43
{36, "Kr"},
44
{37, "Rb"},
45
{38, "Sr"},
46
{39, "Y"},
47
{40, "Zr"},
48
{41, "Nb"},
49
{42, "Mo"},
50
{43, "Tc"},
51
{44, "Ru"},
52
{45, "Rh"},
53
{46, "Pd"},
54
{47, "Ag"},
55
{48, "Cd"},
56
{49, "In"},
57
{50, "Sn"},
58
{51, "Sb"},
59
{52, "Te"},
60
{53, "I"},
61
{54, "Xe"},
62
{55, "Cs"},
63
{56, "Ba"},
64
{57, "La"},
65
{58, "Ce"},
66
{59, "Pr"},
67
{60, "Nd"},
68
{61, "Pm"},
69
{62, "Sm"},
70
{63, "Eu"},
71
{64, "Gd"},
72
{65, "Tb"},
73
{66, "Dy"},
74
{67, "Ho"},
75
{68, "Er"},
76
{69, "Tm"},
77
{70, "Yb"},
78
{71, "Lu"},
79
{72, "Hf"},
80
{73, "Ta"},
81
{74, "W"},
82
{75, "Re"},
83
{76, "Os"},
84
{77, "Ir"},
85
{78, "Pt"},
86
{79, "Au"},
87
{80, "Hg"},
88
{81, "Tl"},
89
{82, "Pb"},
90
{83, "Bi"},
91
{84, "Po"},
92
{85, "At"},
93
{86, "Rn"},
94
{87, "Fr"},
95
{88, "Ra"},
96
{89, "Ac"},
97
{90, "Th"},
98
{91, "Pa"},
99
{92, "U"},
100
{93, "Np"},
101
{94, "Pu"},
102
{95, "Am"},
103
{96, "Cm"},
104
{97, "Bk"},
105
{98, "Cf"},
106
{99, "Es"},
107
{100, "Fm"},
108
{101, "Md"},
109
{102, "No"},
110
{103, "Lr"},
111
{104, "Rf"},
112
{105, "Db"},
113
{106, "Sg"},
114
{107, "Bh"},
115
{108, "Hs"},
116
{109, "Mt"},
117
{110, "Uun"},
118
{111, "Uuu"},
119
{112, "Uub"},
120
{113, "Uut"},
121
{114, "Uuq"},
122
{115, "Uup"},
123
{116, "Uuh"},
124
{117, "Uus"},
125
{118, "Uuo"},
126
{0,"fin"}
127
};
128
 
129
std::ostream & Compteur::operator << (std::ostream & o)const{
130
  const_iterator i=begin();
131
  while (i != end()){
132
    o << i->first << " : " << i->second;
133
    if (++i != end()) o << " ";
134
  }
135
  return o;
136
}
137
 
138
std::ostream & operator << (std::ostream & o, const Compteur & c){
139
  return c.operator << (o);
140
}
141
 
142
double AtomeListe::weight(fraction mult)const{
143
  const AtomeListe * al;
144
  double w=0.0;
104 bpr 145
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
10 reyssat 146
    w=mendelweight(symb)*nb*mult.i/mult.d;
147
  }
148
  else if (Zed==0){ /* cas d'un groupe */
149
    if (group) w+=group->weight(mult*nb);
150
  }
151
  if (suiv) w+=suiv->weight(mult);
152
  return w;
153
}
154
 
155
void AtomeListe::compte(Compteur &c, fraction mult)const{
156
  const AtomeListe * al;
104 bpr 157
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
10 reyssat 158
    std::string key(symb);
159
    c[key] +=1.0*nb*mult.i/mult.d;
160
  }
161
  else if (Zed==0){ /* cas d'un groupe */
162
    if (group) group->compte(c,mult*nb);
163
  }
164
  if (suiv) suiv->compte(c,mult);
165
}
166
 
167
void AtomeListe::numerote(int n){
104 bpr 168
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 169
    no = n;
170
  }
171
  else if (Zed==0){ /* cas d'un groupe */
172
    no = n;
173
    if (group) group->numerote();
174
  }
175
  if (suiv) suiv->numerote(n+1);
176
}
177
 
178
AtomeListe * AtomeListe::triage(AtomeListe * al){
179
  AtomeListe * al1;
104 bpr 180
  if(al->Z()!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 181
    if (al->suiv){
182
      al->suiv = triage(al->suiv);
183
    }
184
    while (al->suiv && al->suiv->Zed!=0 &&
185
           strcmp(al->symbole(), al->suiv->symbole()) > 1){
186
      al1=al; al=al->suiv; al1->suiv=al->suiv; al->suiv=triage(al1);
187
    }
188
  }
189
  else{ /* cas d'un groupe */
190
     if (al->groupe()) al->groupe(triage(al->groupe()));
191
  }
192
  return al;
193
}
194
 
820 georgesk 195
bool AtomeListe::isEqual(const AtomeListe & a2) const {
10 reyssat 196
  std::stringstream s1, s2;
820 georgesk 197
  printnorm(s1);
10 reyssat 198
  a2.printnorm(s2);
104 bpr 199
  return s1.str() == s2.str();
10 reyssat 200
}
201
 
202
void AtomeListe::printcount(std::ostream & o, const fraction& n, int multiple=1) const{
104 bpr 203
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 204
    o << symb;
205
    o << ':' << n << '*' << multiple*nb;
206
  }
207
  else{ /* cas d'un groupe */
208
    if (group) group->printcount(o,n,nb);
209
  }  
210
  if (suiv) {o << ' '; suiv->printcount(o,n,multiple);}
211
}
212
 
213
void AtomeListe::printnorm(std::ostream & o) const{
214
  if (sqbr) o << "[";
104 bpr 215
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 216
    o << symb;
217
    if (nb!=1) o << nb;
218
  }
219
  else{ /* cas d'un groupe */
220
    o << "(";
221
    if (group) group->printnorm(o);
222
    o << ")" << nb;
223
  }  
224
  if (suiv) suiv->printnorm(o);
225
  if (sqbr) o << "]";
226
}
227
 
228
std::ostream & operator << (std::ostream & o, const AtomeListe & l){
229
  int n;
230
  const AtomeListe * al;
231
  if (l.sq()) o << "[";
232
  if(l.Z()>0 || l.Z()<-1){
7222 georgesk 233
    o << "\\mathrm{" << l.symbole() << "}";
10 reyssat 234
  }
104 bpr 235
  else if (l.Z()==-1){ // cas de l'électron
7222 georgesk 236
    o << "\\mathrm{e}";
10 reyssat 237
  }
104 bpr 238
  else{                // cas des groupes parenthésés
10 reyssat 239
    o << "(";
240
    if((al=l.groupe())) o << *al;
241
    o << ")";
242
  }
243
  if((n=l.getmolecularite())>1) o << "_{" << n << "}";
244
  if((al=l.suivant())) o << *al;
245
  if (l.sq()) o << "]";
246
  return o;
247
}
248
 
104 bpr 249
const char* moltypeStr[] = { "aq", "g", "s" };
10 reyssat 250
 
251
const std::string Molec::signature()const{
252
  std::ostringstream o;
253
  o << liste();
254
  if (charge()){
255
    o << "^{";
256
    if(fabs(1.0*charge())!=1) o << fabs(1.0*charge());
257
    if(charge()>0) o << "+}"; else o << "-}";
258
  }
259
  if (t != aqueous) o << moltypeStr[t];
260
  return std::string (o.str());
261
}
262
 
263
bool Molec::printcount(std::ostream & o, bool first) const{
264
  if (!first) o << ", ";
265
  first=false;
266
  printnorm(o);
267
  o << '|';
268
  al-> printcount(o,nb);
269
  return first;
270
}
271
 
272
bool Molec::printelec(std::ostream & o, bool first) const{
273
  if (!first) o << ", ";
274
  first=false;
275
  printnorm(o);
276
  o << '|';
277
  o << nb << '*' << ch;
278
  return first;
279
}
280
 
281
bool Molec::printspecies(std::ostream & o, bool first) const{
282
  if (!first) o << ", ";
283
  first=false;
284
  printnorm(o);
285
  return first;
286
}
287
 
288
void Molec::printnorm(std::ostream & o)const{
289
  if (nb!=1) o << nb << " ";
290
  al-> printnorm(o);
291
  if (ch) {
292
    o << "^";
293
    if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
294
    if(ch>0) o << "+"; else o << "-";
295
  }
7222 georgesk 296
  if (!iswater() && !iselectron()) o << "_"  << moltypeStr[t];
10 reyssat 297
}
298
 
299
void Molec::coeff( fraction f){
300
  nb.i *= f.i;
301
  nb.d *= f.d;
302
  nb.simplifie();
303
}
304
 
104 bpr 305
bool Molec::printNernst(std::ostream & o, const char * prefix){
10 reyssat 306
  switch(t){
307
  case sol : return 0;
308
  case aqueous :
309
    if (iswater() || iselectron()) return 0;
310
    o << prefix << "[" << *al;
311
    if (ch){
312
      o << "^{";
313
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
314
      if(ch>0) o << "+}"; else o << "-}";
315
    }
316
    if (t != aqueous) o << "_{" << moltypeStr[t] << "}";
317
    o  <<"]";
318
    if (nb!=1) {
319
      o << "^{";
320
      printNombre(o);
321
      o << "}";
322
    }
323
    return 1;
324
  case gas :
325
    o << prefix << "P_{" << *al << "}";
326
    if (nb!=1) {
327
      o << "^{";
328
      printNombre(o);
329
      o << "}";
330
    }
331
    return 1;
332
  }
333
}
334
 
472 georgesk 335
bool Molec::printNernstWIMS(std::ostream & o, bool wantedlatex){
336
  if (iswater() || iselectron()) {
337
    return false;
338
  }
339
  switch(t){
340
  case sol : {
341
    return false;
342
  }
343
  case aqueous :
344
    if(wantedlatex){
345
      o <<  "[" << *al;
346
    }else{
347
      o << "["; al->printnorm(o);
348
    }
349
    if (ch){
350
      if(wantedlatex){
351
        o << "^{";
352
      }else{
353
        o << "^";
354
      }
355
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
356
      if(wantedlatex){
357
        if(ch>0) o << "+}"; else o << "-}";
358
      }else{
359
        if(ch>0) o << "+"; else o << "-";
360
      }
361
    }
362
    o  <<"]";
363
    if (nb!=1) {
364
      if(wantedlatex){
365
        o << "^{";
366
        if (nb.d==1){
367
          o << nb.i ;
368
        }
369
        else {
370
          o << "\\frac{" << nb.i << "}{" << nb.d << "}";
371
        }
372
        o << "}";
373
      }else{
374
        o << "^" << nb;
375
      }
376
    }
377
    return true;
378
  case gas :
379
    if(wantedlatex){
380
      o << "P_{" << *al << "}";
381
    }else{
382
      o << "P_"; al->printnorm(o);
383
    }
384
    if (nb!=1) {
385
      if(wantedlatex){
386
        o << "^{";
387
        if (nb.d==1){
388
          o << nb.i ;
389
        }
390
        else {
391
          o << "\\frac{" << nb.i << "}{" << nb.d << "}";
392
        }
393
        o << "}";
394
      }else{
395
        o << "^" << nb;
396
      }
397
    }
398
    return true;
399
  }
400
  return false;
401
}
402
 
10 reyssat 403
bool Molec::iswater()const{
404
  if (t != aqueous) return 0;
7222 georgesk 405
  if (signature()==std::string("\\mathrm{H}_{2}\\mathrm{O}") ||
406
      signature()==std::string("\\mathrm{O}\\mathrm{H}_{2}")) return 1;
10 reyssat 407
  else return 0;
408
}
409
 
410
bool Molec::iselectron()const{
7222 georgesk 411
  return (signature()==std::string("\\mathrm{e}^{-}"));
10 reyssat 412
}
413
 
414
fraction Molec::nbelectron()const{
415
  if (iselectron()) return nb;
416
  else return fraction(0);
417
}
418
 
104 bpr 419
void Molec::add(fraction f){
420
  nb = nb+f;
421
}
422
 
423
void Molec::sub(fraction f){
424
  nb = nb-f;
425
}
426
 
10 reyssat 427
void Molec::printNombre(std::ostream & o)const{
428
  if (nb.d==1){
429
    o << nb.i << "\\,";
430
  }
431
  else {
432
    o << "\\frac{" << nb.i << "}{" << nb.d << "}\\,";
433
  }
434
}
435
 
436
std::ostream & operator << (std::ostream & o, const Molec & m){
437
  if (m.nombre() != 1) m.printNombre(o);
438
  o << m.liste();
439
  if (m.charge()){
440
    o << "^{";
441
    if(fabs(1.0*m.charge())!=1) o << fabs(1.0*m.charge());
442
    if(m.charge()>0) o << "+}"; else o << "-}";
443
  }
7222 georgesk 444
  if (m.typage() != aqueous && ! m.iselectron()) o << "_{" << moltypeStr[m.typage()] << "}";
10 reyssat 445
  return o;
446
}
447
 
104 bpr 448
int Membre::findMol(const Molec * m){
449
  // returns the index of a molecule with the same atomlist if any
450
  // else returns -1.
451
  int result=-1;
452
  for(int i=0; i<size(); i++){
453
    if ((*this)[i]->eqMol(m)) result=i;
454
  }
455
  return result;
456
}
457
 
458
void Membre::addMol(const Molec * m){
459
  int i = findMol(m);
460
  if (i < 0){
461
    push_back(new Molec(*m));
462
  } else {
463
    (*this)[i]->add(m->nombre());
464
  }
465
}
466
 
467
void Membre::addMembre(const Membre * m){
468
  for(int i=0; i<m->size(); i++){
469
    addMol((*m)[i]);
470
  }
471
}
472
 
473
void Membre::eraseNull(){
474
  Membre m(*this);
475
  clear();
476
  for(int i=0; i < m.size();i++){
477
    if (m[i]->nombre().i>0) push_back(m[i]);
478
  }
479
}
480
 
10 reyssat 481
void Membre::compte(Compteur & c)const{
482
  for(int i =0; i < size(); i++){
483
    operator [] (i)->compte(c);
484
  }
485
}
486
 
487
void Membre::numerote(){
488
  for (int i=0; i < size(); i++){
489
    operator [](i)->numero(i);
490
    operator [](i)->liste().numerote();
491
  }
492
}
493
 
494
void Membre::triage(){
495
  int i,j;
496
  for (i=0; i < size(); i++){
497
    operator [](i)->triage();
498
  }
499
  for (i=0; i < size(); i++){
500
    for (j=i+1; j < size(); j++){
501
      if (operator [](i)->signature() > operator [](j)->signature()){
502
        Molec * m = operator [](i);
503
        operator [](i) = operator [](j);
504
        operator [](j) = m;
505
      }
506
    }
507
  }
508
}
509
 
510
void Membre::printcount(std::ostream & o) const{
511
  bool first=true;
512
  for(int i=0; i < size(); i++){
513
    first=operator[](i)->printcount(o,first);
514
  }
515
}
516
 
517
void Membre::printelec(std::ostream & o) const{
518
  bool first=true;
519
  for(int i=0; i < size(); i++){
520
    first=operator[](i)->printelec(o,first);
521
  }
522
}
523
 
524
void Membre::printspecies(std::ostream & o) const{
525
  bool first=true;
526
  for(int i=0; i < size(); i++){
527
    first=operator[](i)->printspecies(o,first);
528
  }
529
}
530
 
531
void Membre::printnorm(std::ostream & o) const{
532
  for(int i=0; i < size(); i++){
533
    operator[](i)->printnorm(o);
534
    if (i < size()-1) o << " + ";
535
  }
536
}
537
 
538
void Membre::printweight(std::ostream & o) const{
539
  for(int i=0; i < size(); i++){
540
    o << operator[](i)->weight();
541
    if (i < size()-1) o << " ";
542
  }
543
}
544
 
545
void Membre::coeff( fraction f){
546
  for (int i=0; i<size(); i++) operator[](i)->coeff(f);
547
}
548
 
549
int Membre::printableNernst(){
550
  int result=0;
551
  for (int i=0; i<size(); i++) {
552
    if (operator[](i)->typage() != sol &&
553
        !operator[](i)->iswater() &&
554
        !operator[](i)->iselectron()) result =1;
555
  }  
556
  return result;
557
}
558
 
559
bool Membre::redox()const{
560
  for (int i=0; i<size(); i++){
104 bpr 561
    if ((*this)[i]->iselectron()) /* c'est un électron */ return 1;
10 reyssat 562
  }
563
  return 0;
564
}
565
 
566
fraction  Membre::nbelectron()const{
567
  fraction result(0);
568
 
569
  for(int i = 0; i<size(); i++) result=result+(*this)[i]->nbelectron();
570
  return result;
571
}
572
 
573
void Membre::printNernst(std::ostream & o){
574
  bool printed = 0;
104 bpr 575
  const char * prefix="";
10 reyssat 576
  for (int i=0; i<size(); i++) {
577
    if (i>0) prefix="\\,";
578
    if (operator[](i)->printNernst(o, prefix)){
579
      printed = 1;
580
    }
581
  }
582
  if (!printed) o << "1";
583
}
584
 
472 georgesk 585
void Membre::printNernstWIMS(std::ostream & o, bool wantedlatex){
586
  bool printed = false;
587
  bool addcomma = false;
588
  for (int i=0; i<size(); i++) {
589
    std::ostringstream w;
590
    if (operator[](i)->printNernstWIMS(w,wantedlatex)){
591
      if (addcomma) o << ", ";
592
      o << w.str();
593
      printed = true;
594
      addcomma = true;
595
    } else {
596
      addcomma = false;
597
    }
598
  }
599
  if (!printed) o << "1";
600
}
601
 
10 reyssat 602
std::ostream & operator << (std::ostream & o, const Membre & m){
603
  for(int i=0; i < m.size()-1; i++){
604
    o << *m[i] << "\\,+\\,";
605
  }
606
  o << *m[m.size()-1];
607
  return o;
608
}
609
 
610
Membre operator & (Membre & m1, Membre & m2){
611
  Membre result;
820 georgesk 612
  //result.printnorm(std::cout);
10 reyssat 613
  fraction min(1);
614
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
615
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
820 georgesk 616
      if ((*i)->eqMol(*j)){
10 reyssat 617
        Molec *m = new Molec(**i);
618
        if ((*i)->nb > (*j)->nb){
619
          min=(*j)->nb;
620
        }else{
621
          min=(*i)->nb;
622
        }
623
        m->nb=min;
624
        result.push_back(m);
625
      }
626
    }
627
  }
628
  return result;
629
}
630
 
631
Membre operator - (Membre & m1, Membre & m2){
632
  Membre result;
633
  fraction diff(1);
634
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
635
    Molec *m = new Molec(**i);
636
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
820 georgesk 637
      if ((*i)->eqMol(*j)){
10 reyssat 638
        diff=(*i)->nb - (*j)->nb;
639
        m->nb=diff;
640
      }
641
    }
642
    result.push_back(m);
643
  }
644
  return result;
645
}
646
 
104 bpr 647
bool Chemeq::valdefined()const{
648
  return val > MINVAL;
649
}
650
 
651
void Chemeq::addChemeq(const Chemeq * c){
652
  if (valdefined() && c->valdefined()){
653
    long double e1=enthalpy(), e2=c->enthalpy();
654
    fraction n1=nbelectron(), n2=c->nbelectron();
655
    long double e = e1+e2;
656
    fraction n=n1+n2;
472 georgesk 657
    if (n.i==0) val=exp(-e/R/T0);
104 bpr 658
    else val=-e*n.d/n.i/Faraday;
659
  } else {
660
    val=MINVAL;
661
  }
662
  gauche->addMembre(c->gauche);
663
  droit->addMembre(c->droit);
664
  simplifie(true);
665
}
666
 
667
void Chemeq::subChemeq(const Chemeq * c){
668
  if (valdefined() && c->valdefined()){
669
    long double e1=enthalpy(), e2=c->enthalpy();
670
    fraction n1=nbelectron(), n2=c->nbelectron();
671
    long double e = e1-e2;
672
    fraction n=n1-n2;
673
    if (n.i==0) {
472 georgesk 674
    val=exp(-e/R/T0);
104 bpr 675
    } else{
676
      val=-e*n.d/n.i/Faraday;
677
    }
678
  } else {
679
    val=MINVAL;
680
  }
681
  gauche->addMembre(c->droit);
682
  droit->addMembre(c->gauche);
683
  simplifie(true);
684
}
685
 
686
long double Chemeq::enthalpy() const{
687
  fraction n=nbelectron();
688
  if (redox()){
689
    return -val*n.i/n.d*Faraday;
690
  } else {
472 georgesk 691
    return -R*T0*log(val);
104 bpr 692
  }
693
}
694
 
695
void Chemeq::simplifie(bool tri=false){
696
  Membre communs(*gauche & *droit);
697
  if (communs.size()>0){
698
    Membre * g, *d;
699
    g= new Membre(*gauche - communs);
700
    d= new Membre(*droit  - communs);
701
    delete gauche;
702
    delete droit;
703
    gauche=g;
704
    droit =d;
705
  }
706
  gauche->eraseNull();
707
  droit->eraseNull();
708
  if (tri){
709
    numerote();
710
    triage();
711
  }
712
}
713
 
10 reyssat 714
void Chemeq::printnorm(std::ostream & o){
715
  gauche->printnorm(o);
716
  o << " -> ";
717
  droit->printnorm(o);
104 bpr 718
  if (val>MINVAL){
10 reyssat 719
    o << " (";
720
    if (cste!=std::string("")) o << cste << " = ";
721
    o << val;
722
    if (redox()) o << " V";
723
    o << ")";
724
  }
725
}
726
 
727
void Chemeq::printcount(std::ostream & o) const {
728
  gauche->printcount(o);
729
  o << "; ";
730
  droit->printcount(o);
731
}
732
 
733
void Chemeq::printelec(std::ostream & o) const {
734
  gauche->printelec(o);
735
  o << "; ";
736
  droit->printelec(o);
737
}
738
 
739
void Chemeq::printspecies(std::ostream & o) const {
740
  gauche->printspecies(o);
741
  o << "; ";
742
  droit->printspecies(o);
743
}
744
 
745
void Chemeq::printweight(std::ostream & o) const{
746
  gauche->printweight(o);
747
  o << " ";
748
  droit->printweight(o);
749
}
750
 
751
std::string Chemeq::equilibre(){
752
  std::ostringstream s;
753
  Compteur cpg, cpd;
754
  gauche->compte(cpg);
755
  droit->compte(cpd);
756
  if(cpg==cpd) s << "OK";
757
  else s << "ERROR " << cpg << " / " << cpd;
758
  return std::string(s.str());
759
}
760
 
761
void Chemeq::coeff1(){
762
  fraction mult = gauche->operator[](0)->nombre();
763
  mult.inverse();
764
  gauche->coeff(mult);
765
  droit->coeff(mult);
104 bpr 766
  simplifie();
110 bpr 767
  if (!redox() && valdefined()){
104 bpr 768
    val = val*mult.i/mult.d;
10 reyssat 769
  }
104 bpr 770
}
771
 
772
void Chemeq::multiply(int num, int den){
773
  fraction mult(num,den);
774
  gauche->coeff(mult);
775
  droit->coeff(mult);
776
  simplifie();
110 bpr 777
  if (!redox() && valdefined()){
10 reyssat 778
    val = val*mult.i/mult.d;
779
  }
780
}
781
 
782
bool Chemeq::redox()const{
783
  return gauche->redox() || droit->redox();
784
}
785
 
472 georgesk 786
void Chemeq::printNernst(std::ostream & o,
787
                         std::ostream & w,
788
                         bool wantedlatex){
10 reyssat 789
  Membre * ga, * dr;
790
  if (!redox()){
791
    if (gauche->printableNernst()){
792
      o << "\\frac{";
793
      droit->printNernst(o);
794
      o << "}{";
795
      gauche->printNernst(o);
796
      o << "}";
797
    }
798
    else {
799
      droit->printNernst(o);
800
    }
472 georgesk 801
    droit->printNernstWIMS(w,wantedlatex);
802
    w << "; ";
803
    gauche->printNernstWIMS(w,wantedlatex);
104 bpr 804
    if (val > MINVAL) {
10 reyssat 805
      o << "\\,=\\,";
806
      if (cste!=std::string("")) o << cste << "\\,=\\,";
104 bpr 807
      o << valeur_latex();
472 georgesk 808
      if(wantedlatex){
809
        w << "; " << valeur_latex();
810
      }else{
811
        w << "; " << val;
812
      }
10 reyssat 813
    }
814
    else{
815
      o << "\\,=\\,K";
472 georgesk 816
      w << "; K";
10 reyssat 817
    }
818
  }
472 georgesk 819
  else{ /* c'est une réaction redox  */
10 reyssat 820
    o << "E\\,=\\,";
472 georgesk 821
    if(wantedlatex){
822
      w << "E\\,=\\,";
823
    }else{
824
      w << "E=";
825
    }
104 bpr 826
    if (val > MINVAL) {
10 reyssat 827
      o << val;
472 georgesk 828
      w << val << ";";
10 reyssat 829
    }
830
    else{
831
      o << "E_{0}";
472 georgesk 832
      if(wantedlatex){
833
        w << "E_{0};";
834
      }else{
835
        w << "E0;";
836
      }
10 reyssat 837
    }
838
    o << "\\,+\\,\\frac{R\\,T}{";
839
    o << gauche->nbelectron()+droit->nbelectron() << "\\,F}";
840
    o << "\\log";
472 georgesk 841
    w << gauche->nbelectron()+droit->nbelectron() << ";";
104 bpr 842
    if (gauche->redox()){ /* c'est une réduction */
10 reyssat 843
      ga=gauche; dr=droit;
844
    }
845
    else{ /* c'est une oxydation */
846
      ga=droit; dr=gauche;
847
    }
848
    if (dr->printableNernst()){
472 georgesk 849
      o << "\\frac{";
850
      ga->printNernst(o);
851
      o << "}{";
852
      dr->printNernst(o);
853
      o << "}";
854
    }
855
    else {
856
      o << "(";
857
      ga->printNernst(o);
858
      o << ")";
859
    }
860
    // implanter la sortie pour Wims ici.
861
    dr->printNernstWIMS(w,wantedlatex);
862
    w << "; ";
863
    ga->printNernstWIMS(w,wantedlatex);
10 reyssat 864
  }
865
}
866
 
104 bpr 867
std::string Chemeq::valeur_latex()const{
868
  std::ostringstream so;
869
  so << val;
870
  std::string s(so.str());
871
  std::string::size_type epos=s.find('e',0);
872
  if (epos!=std::string::npos){
873
    s.erase(epos,1);
874
    s.insert(epos,"\\times 10^{");
875
    s=s+"}";
876
  }
877
  return (std::string) s;
878
}
879
 
10 reyssat 880
std::ostream & operator << (std::ostream & o, const Chemeq & c){
6872 georgesk 881
  o << *c.membregauche() << "\\,\\longrightarrow\\," << *c.membredroit();
104 bpr 882
  if (c.valeur() > MINVAL) {
10 reyssat 883
    o << "\\,(";
884
    if (c.constante()!=std::string("")) o << c.constante() << "\\,=\\,";
104 bpr 885
    o << c.valeur_latex();
10 reyssat 886
    if (c.redox()) o << " V";
887
    o << ")";
888
  }
889
  return o;
890
}
891
 
892
std::ostream & operator << (std::ostream & o, fraction f){
893
  o << f.i;
894
  if (f.d!=1) o << '/' << f.d;
895
  return o;
896
}
897
 
898
fraction operator * (fraction f, int m){
899
  fraction result = fraction(f.i*m, f.d);
900
  result.simplifie();
901
  return result;
902
}
903
 
904
fraction operator * (int m, fraction f){
905
  fraction result = fraction(f.i*m, f.d);
906
  result.simplifie();
907
  return result;
908
}
909
 
910
fraction operator * (fraction f, fraction m)
911
{
912
  fraction result = fraction(f.i*m.i, f.d*m.d);
913
  result.simplifie();
914
  return result;
915
}
916
 
917
fraction operator + (fraction f, fraction g){
918
  fraction result = fraction(f.i*g.d+g.i*f.d, f.d*g.d);
919
  result.simplifie();
920
  return result;
921
}
922
 
923
fraction operator - (fraction f, fraction g){
924
  fraction result = fraction(f.i*g.d-g.i*f.d, f.d*g.d);
925
  result.simplifie();
926
  return result;
927
}
928
 
104 bpr 929
const fraction & minFraction(const fraction& f1, const fraction &f2){
930
  if (f1.i*f2.d > f2.i*f1.d) return f1;
931
  else return f2;
932
}
933
 
10 reyssat 934
void fraction::simplifie(){
935
  int maxprem = 23;
936
  int premiers[]={2,3,5,7,11,13,17,19,23,29};
937
  int n;
938
 
939
  for (n=0; premiers[n]<= maxprem; n++){
940
    while (i % premiers[n] == 0 && d % premiers[n] == 0){
941
      i /= premiers[n]; d /= premiers[n];
942
    }
943
  }
944
}
945
 
946
bool operator > (fraction f, int i){
947
  return f.i > f.d*i;
948
}
949
 
950
bool operator > (fraction f1, fraction f2){
951
  return f1.i*f2.d > f1.d*f2.i;
952
}
953
 
954
bool operator != (fraction f, int i){
955
  return f.i != f.d*i;
956
}
957
 
958
double mendelweight(int i){
959
  if (i>=0) return strtod (table[i].info[WEIGHT],0); else return 0.0;
960
}
961
 
962
int findmendel(const char * symb){
963
  int i=0;
964
  while (table[i].info[0] && strcmp(table[i].info[SYMBOL], symb) != 0) i++;
965
  if (table[i].info[0]) return i; else return -1;
966
}
967
 
968
double mendelweight(const char * symb){
969
  int i;
970
  i = findmendel(symb);
971
  return mendelweight(i);
972
}