Subversion Repositories wimsdev

Rev

Rev 13121 | Rev 17747 | 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{
13325 georgesk 143
  // const AtomeListe * al;
10 reyssat 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{
13325 georgesk 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
 
12963 georgesk 249
// from the header file:
250
// typedef enum { aqueous, aqueous_explicit, gas, liquid, sol } moltype;
251
const char* moltypeStr[] = { "", "(aq)", "(g)", "(l)", "(s)" };
10 reyssat 252
 
253
const std::string Molec::signature()const{
254
  std::ostringstream o;
255
  o << liste();
256
  if (charge()){
257
    o << "^{";
258
    if(fabs(1.0*charge())!=1) o << fabs(1.0*charge());
259
    if(charge()>0) o << "+}"; else o << "-}";
260
  }
261
  if (t != aqueous) o << moltypeStr[t];
262
  return std::string (o.str());
263
}
264
 
265
bool Molec::printcount(std::ostream & o, bool first) const{
266
  if (!first) o << ", ";
267
  first=false;
268
  printnorm(o);
269
  o << '|';
270
  al-> printcount(o,nb);
271
  return first;
272
}
273
 
274
bool Molec::printelec(std::ostream & o, bool first) const{
275
  if (!first) o << ", ";
276
  first=false;
277
  printnorm(o);
278
  o << '|';
279
  o << nb << '*' << ch;
280
  return first;
281
}
282
 
283
bool Molec::printspecies(std::ostream & o, bool first) const{
284
  if (!first) o << ", ";
285
  first=false;
286
  printnorm(o);
287
  return first;
288
}
289
 
290
void Molec::printnorm(std::ostream & o)const{
291
  if (nb!=1) o << nb << " ";
292
  al-> printnorm(o);
293
  if (ch) {
294
    o << "^";
295
    if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
296
    if(ch>0) o << "+"; else o << "-";
297
  }
12963 georgesk 298
  // the aqueous type is the default, so: no _(aq)
299
  // to have this suffix, on must make the type to aqueous_explicit
300
  if (!iswater() && !iselectron() && t != aqueous) o << "_"  << moltypeStr[t];
10 reyssat 301
}
302
 
303
void Molec::coeff( fraction f){
304
  nb.i *= f.i;
305
  nb.d *= f.d;
306
  nb.simplifie();
307
}
308
 
104 bpr 309
bool Molec::printNernst(std::ostream & o, const char * prefix){
10 reyssat 310
  switch(t){
13325 georgesk 311
  case sol :
312
  case liquid:
313
    return 0;
10 reyssat 314
  case aqueous :
13325 georgesk 315
  case aqueous_explicit:
10 reyssat 316
    if (iswater() || iselectron()) return 0;
317
    o << prefix << "[" << *al;
318
    if (ch){
319
      o << "^{";
320
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
321
      if(ch>0) o << "+}"; else o << "-}";
322
    }
323
    if (t != aqueous) o << "_{" << moltypeStr[t] << "}";
324
    o  <<"]";
325
    if (nb!=1) {
326
      o << "^{";
327
      printNombre(o);
328
      o << "}";
329
    }
330
    return 1;
331
  case gas :
332
    o << prefix << "P_{" << *al << "}";
333
    if (nb!=1) {
334
      o << "^{";
335
      printNombre(o);
336
      o << "}";
337
    }
338
    return 1;
339
  }
13325 georgesk 340
  return 0;
10 reyssat 341
}
342
 
472 georgesk 343
bool Molec::printNernstWIMS(std::ostream & o, bool wantedlatex){
344
  if (iswater() || iselectron()) {
345
    return false;
346
  }
347
  switch(t){
13325 georgesk 348
  case sol :
349
  case liquid :
350
    {
351
      return false;
352
    }
472 georgesk 353
  case aqueous :
13325 georgesk 354
  case aqueous_explicit :
472 georgesk 355
    if(wantedlatex){
356
      o <<  "[" << *al;
357
    }else{
358
      o << "["; al->printnorm(o);
359
    }
360
    if (ch){
361
      if(wantedlatex){
362
        o << "^{";
363
      }else{
364
        o << "^";
365
      }
366
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
367
      if(wantedlatex){
368
        if(ch>0) o << "+}"; else o << "-}";
369
      }else{
370
        if(ch>0) o << "+"; else o << "-";
371
      }
372
    }
373
    o  <<"]";
374
    if (nb!=1) {
375
      if(wantedlatex){
376
        o << "^{";
377
        if (nb.d==1){
378
          o << nb.i ;
379
        }
380
        else {
381
          o << "\\frac{" << nb.i << "}{" << nb.d << "}";
382
        }
383
        o << "}";
384
      }else{
385
        o << "^" << nb;
386
      }
387
    }
388
    return true;
389
  case gas :
390
    if(wantedlatex){
391
      o << "P_{" << *al << "}";
392
    }else{
393
      o << "P_"; al->printnorm(o);
394
    }
395
    if (nb!=1) {
396
      if(wantedlatex){
397
        o << "^{";
398
        if (nb.d==1){
399
          o << nb.i ;
400
        }
401
        else {
402
          o << "\\frac{" << nb.i << "}{" << nb.d << "}";
403
        }
404
        o << "}";
405
      }else{
406
        o << "^" << nb;
407
      }
408
    }
409
    return true;
410
  }
411
  return false;
412
}
413
 
10 reyssat 414
bool Molec::iswater()const{
415
  if (t != aqueous) return 0;
7222 georgesk 416
  if (signature()==std::string("\\mathrm{H}_{2}\\mathrm{O}") ||
417
      signature()==std::string("\\mathrm{O}\\mathrm{H}_{2}")) return 1;
10 reyssat 418
  else return 0;
419
}
420
 
421
bool Molec::iselectron()const{
7222 georgesk 422
  return (signature()==std::string("\\mathrm{e}^{-}"));
10 reyssat 423
}
424
 
425
fraction Molec::nbelectron()const{
426
  if (iselectron()) return nb;
427
  else return fraction(0);
428
}
429
 
104 bpr 430
void Molec::add(fraction f){
431
  nb = nb+f;
432
}
433
 
434
void Molec::sub(fraction f){
435
  nb = nb-f;
436
}
437
 
10 reyssat 438
void Molec::printNombre(std::ostream & o)const{
439
  if (nb.d==1){
440
    o << nb.i << "\\,";
441
  }
442
  else {
443
    o << "\\frac{" << nb.i << "}{" << nb.d << "}\\,";
444
  }
445
}
446
 
447
std::ostream & operator << (std::ostream & o, const Molec & m){
448
  if (m.nombre() != 1) m.printNombre(o);
449
  o << m.liste();
450
  if (m.charge()){
451
    o << "^{";
452
    if(fabs(1.0*m.charge())!=1) o << fabs(1.0*m.charge());
453
    if(m.charge()>0) o << "+}"; else o << "-}";
454
  }
7222 georgesk 455
  if (m.typage() != aqueous && ! m.iselectron()) o << "_{" << moltypeStr[m.typage()] << "}";
10 reyssat 456
  return o;
457
}
458
 
104 bpr 459
int Membre::findMol(const Molec * m){
460
  // returns the index of a molecule with the same atomlist if any
461
  // else returns -1.
462
  int result=-1;
13325 georgesk 463
  for(unsigned int i=0; i<size(); i++){
104 bpr 464
    if ((*this)[i]->eqMol(m)) result=i;
465
  }
466
  return result;
467
}
468
 
469
void Membre::addMol(const Molec * m){
470
  int i = findMol(m);
471
  if (i < 0){
472
    push_back(new Molec(*m));
473
  } else {
474
    (*this)[i]->add(m->nombre());
475
  }
476
}
477
 
478
void Membre::addMembre(const Membre * m){
13325 georgesk 479
  for(unsigned int i=0; i<m->size(); i++){
104 bpr 480
    addMol((*m)[i]);
481
  }
482
}
483
 
484
void Membre::eraseNull(){
485
  Membre m(*this);
486
  clear();
13325 georgesk 487
  for(unsigned int i=0; i < m.size();i++){
104 bpr 488
    if (m[i]->nombre().i>0) push_back(m[i]);
489
  }
490
}
491
 
10 reyssat 492
void Membre::compte(Compteur & c)const{
13325 georgesk 493
  for(unsigned int i =0; i < size(); i++){
10 reyssat 494
    operator [] (i)->compte(c);
495
  }
496
}
497
 
498
void Membre::numerote(){
13325 georgesk 499
  for (unsigned int i=0; i < size(); i++){
10 reyssat 500
    operator [](i)->numero(i);
501
    operator [](i)->liste().numerote();
502
  }
503
}
504
 
505
void Membre::triage(){
13325 georgesk 506
  unsigned int i,j;
10 reyssat 507
  for (i=0; i < size(); i++){
508
    operator [](i)->triage();
509
  }
510
  for (i=0; i < size(); i++){
511
    for (j=i+1; j < size(); j++){
512
      if (operator [](i)->signature() > operator [](j)->signature()){
513
        Molec * m = operator [](i);
514
        operator [](i) = operator [](j);
515
        operator [](j) = m;
516
      }
517
    }
518
  }
519
}
520
 
521
void Membre::printcount(std::ostream & o) const{
522
  bool first=true;
13325 georgesk 523
  for(unsigned int i=0; i < size(); i++){
10 reyssat 524
    first=operator[](i)->printcount(o,first);
525
  }
526
}
527
 
528
void Membre::printelec(std::ostream & o) const{
529
  bool first=true;
13325 georgesk 530
  for(unsigned int i=0; i < size(); i++){
10 reyssat 531
    first=operator[](i)->printelec(o,first);
532
  }
533
}
534
 
535
void Membre::printspecies(std::ostream & o) const{
536
  bool first=true;
13325 georgesk 537
  for(unsigned int i=0; i < size(); i++){
10 reyssat 538
    first=operator[](i)->printspecies(o,first);
539
  }
540
}
541
 
542
void Membre::printnorm(std::ostream & o) const{
13325 georgesk 543
  for(unsigned int i=0; i < size(); i++){
10 reyssat 544
    operator[](i)->printnorm(o);
545
    if (i < size()-1) o << " + ";
546
  }
547
}
548
 
549
void Membre::printweight(std::ostream & o) const{
13325 georgesk 550
  for(unsigned int i=0; i < size(); i++){
10 reyssat 551
    o << operator[](i)->weight();
552
    if (i < size()-1) o << " ";
553
  }
554
}
555
 
556
void Membre::coeff( fraction f){
13325 georgesk 557
  for (unsigned int i=0; i<size(); i++) operator[](i)->coeff(f);
10 reyssat 558
}
559
 
560
int Membre::printableNernst(){
561
  int result=0;
13325 georgesk 562
  for (unsigned int i=0; i<size(); i++) {
10 reyssat 563
    if (operator[](i)->typage() != sol &&
564
        !operator[](i)->iswater() &&
565
        !operator[](i)->iselectron()) result =1;
566
  }  
567
  return result;
568
}
569
 
570
bool Membre::redox()const{
13325 georgesk 571
  for (unsigned int i=0; i<size(); i++){
104 bpr 572
    if ((*this)[i]->iselectron()) /* c'est un électron */ return 1;
10 reyssat 573
  }
574
  return 0;
575
}
576
 
577
fraction  Membre::nbelectron()const{
578
  fraction result(0);
579
 
13325 georgesk 580
  for(unsigned int i = 0; i<size(); i++) result=result+(*this)[i]->nbelectron();
10 reyssat 581
  return result;
582
}
583
 
584
void Membre::printNernst(std::ostream & o){
585
  bool printed = 0;
104 bpr 586
  const char * prefix="";
13325 georgesk 587
  for (unsigned int i=0; i<size(); i++) {
10 reyssat 588
    if (i>0) prefix="\\,";
589
    if (operator[](i)->printNernst(o, prefix)){
590
      printed = 1;
591
    }
592
  }
593
  if (!printed) o << "1";
594
}
595
 
472 georgesk 596
void Membre::printNernstWIMS(std::ostream & o, bool wantedlatex){
597
  bool printed = false;
598
  bool addcomma = false;
13325 georgesk 599
  for (unsigned int i=0; i<size(); i++) {
472 georgesk 600
    std::ostringstream w;
601
    if (operator[](i)->printNernstWIMS(w,wantedlatex)){
602
      if (addcomma) o << ", ";
603
      o << w.str();
604
      printed = true;
605
      addcomma = true;
606
    } else {
607
      addcomma = false;
608
    }
609
  }
610
  if (!printed) o << "1";
611
}
612
 
10 reyssat 613
std::ostream & operator << (std::ostream & o, const Membre & m){
13325 georgesk 614
  for(unsigned int i=0; i < m.size()-1; i++){
10 reyssat 615
    o << *m[i] << "\\,+\\,";
616
  }
617
  o << *m[m.size()-1];
618
  return o;
619
}
620
 
621
Membre operator & (Membre & m1, Membre & m2){
622
  Membre result;
820 georgesk 623
  //result.printnorm(std::cout);
10 reyssat 624
  fraction min(1);
625
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
626
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
820 georgesk 627
      if ((*i)->eqMol(*j)){
10 reyssat 628
        Molec *m = new Molec(**i);
629
        if ((*i)->nb > (*j)->nb){
630
          min=(*j)->nb;
631
        }else{
632
          min=(*i)->nb;
633
        }
634
        m->nb=min;
635
        result.push_back(m);
636
      }
637
    }
638
  }
639
  return result;
640
}
641
 
642
Membre operator - (Membre & m1, Membre & m2){
643
  Membre result;
644
  fraction diff(1);
645
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
646
    Molec *m = new Molec(**i);
647
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
820 georgesk 648
      if ((*i)->eqMol(*j)){
10 reyssat 649
        diff=(*i)->nb - (*j)->nb;
650
        m->nb=diff;
651
      }
652
    }
653
    result.push_back(m);
654
  }
655
  return result;
656
}
657
 
104 bpr 658
bool Chemeq::valdefined()const{
659
  return val > MINVAL;
660
}
661
 
662
void Chemeq::addChemeq(const Chemeq * c){
663
  if (valdefined() && c->valdefined()){
664
    long double e1=enthalpy(), e2=c->enthalpy();
665
    fraction n1=nbelectron(), n2=c->nbelectron();
666
    long double e = e1+e2;
667
    fraction n=n1+n2;
472 georgesk 668
    if (n.i==0) val=exp(-e/R/T0);
104 bpr 669
    else val=-e*n.d/n.i/Faraday;
670
  } else {
671
    val=MINVAL;
672
  }
673
  gauche->addMembre(c->gauche);
674
  droit->addMembre(c->droit);
675
  simplifie(true);
676
}
677
 
678
void Chemeq::subChemeq(const Chemeq * c){
679
  if (valdefined() && c->valdefined()){
680
    long double e1=enthalpy(), e2=c->enthalpy();
681
    fraction n1=nbelectron(), n2=c->nbelectron();
682
    long double e = e1-e2;
683
    fraction n=n1-n2;
684
    if (n.i==0) {
472 georgesk 685
    val=exp(-e/R/T0);
104 bpr 686
    } else{
687
      val=-e*n.d/n.i/Faraday;
688
    }
689
  } else {
690
    val=MINVAL;
691
  }
692
  gauche->addMembre(c->droit);
693
  droit->addMembre(c->gauche);
694
  simplifie(true);
695
}
696
 
697
long double Chemeq::enthalpy() const{
698
  fraction n=nbelectron();
699
  if (redox()){
700
    return -val*n.i/n.d*Faraday;
701
  } else {
472 georgesk 702
    return -R*T0*log(val);
104 bpr 703
  }
704
}
705
 
706
void Chemeq::simplifie(bool tri=false){
707
  Membre communs(*gauche & *droit);
708
  if (communs.size()>0){
709
    Membre * g, *d;
710
    g= new Membre(*gauche - communs);
711
    d= new Membre(*droit  - communs);
712
    delete gauche;
713
    delete droit;
714
    gauche=g;
715
    droit =d;
716
  }
717
  gauche->eraseNull();
718
  droit->eraseNull();
719
  if (tri){
720
    numerote();
721
    triage();
722
  }
723
}
724
 
10 reyssat 725
void Chemeq::printnorm(std::ostream & o){
726
  gauche->printnorm(o);
727
  o << " -> ";
728
  droit->printnorm(o);
104 bpr 729
  if (val>MINVAL){
10 reyssat 730
    o << " (";
731
    if (cste!=std::string("")) o << cste << " = ";
732
    o << val;
733
    if (redox()) o << " V";
734
    o << ")";
735
  }
736
}
737
 
738
void Chemeq::printcount(std::ostream & o) const {
739
  gauche->printcount(o);
740
  o << "; ";
741
  droit->printcount(o);
742
}
743
 
744
void Chemeq::printelec(std::ostream & o) const {
745
  gauche->printelec(o);
746
  o << "; ";
747
  droit->printelec(o);
748
}
749
 
750
void Chemeq::printspecies(std::ostream & o) const {
751
  gauche->printspecies(o);
752
  o << "; ";
753
  droit->printspecies(o);
754
}
755
 
756
void Chemeq::printweight(std::ostream & o) const{
757
  gauche->printweight(o);
758
  o << " ";
759
  droit->printweight(o);
760
}
761
 
762
std::string Chemeq::equilibre(){
763
  std::ostringstream s;
764
  Compteur cpg, cpd;
765
  gauche->compte(cpg);
766
  droit->compte(cpd);
767
  if(cpg==cpd) s << "OK";
768
  else s << "ERROR " << cpg << " / " << cpd;
769
  return std::string(s.str());
770
}
771
 
772
void Chemeq::coeff1(){
773
  fraction mult = gauche->operator[](0)->nombre();
774
  mult.inverse();
775
  gauche->coeff(mult);
776
  droit->coeff(mult);
104 bpr 777
  simplifie();
110 bpr 778
  if (!redox() && valdefined()){
104 bpr 779
    val = val*mult.i/mult.d;
10 reyssat 780
  }
104 bpr 781
}
782
 
783
void Chemeq::multiply(int num, int den){
784
  fraction mult(num,den);
785
  gauche->coeff(mult);
786
  droit->coeff(mult);
787
  simplifie();
110 bpr 788
  if (!redox() && valdefined()){
10 reyssat 789
    val = val*mult.i/mult.d;
790
  }
791
}
792
 
793
bool Chemeq::redox()const{
794
  return gauche->redox() || droit->redox();
795
}
796
 
472 georgesk 797
void Chemeq::printNernst(std::ostream & o,
798
                         std::ostream & w,
799
                         bool wantedlatex){
10 reyssat 800
  Membre * ga, * dr;
801
  if (!redox()){
802
    if (gauche->printableNernst()){
803
      o << "\\frac{";
804
      droit->printNernst(o);
805
      o << "}{";
806
      gauche->printNernst(o);
807
      o << "}";
808
    }
809
    else {
810
      droit->printNernst(o);
811
    }
472 georgesk 812
    droit->printNernstWIMS(w,wantedlatex);
813
    w << "; ";
814
    gauche->printNernstWIMS(w,wantedlatex);
104 bpr 815
    if (val > MINVAL) {
10 reyssat 816
      o << "\\,=\\,";
817
      if (cste!=std::string("")) o << cste << "\\,=\\,";
104 bpr 818
      o << valeur_latex();
472 georgesk 819
      if(wantedlatex){
820
        w << "; " << valeur_latex();
821
      }else{
822
        w << "; " << val;
823
      }
10 reyssat 824
    }
825
    else{
826
      o << "\\,=\\,K";
472 georgesk 827
      w << "; K";
10 reyssat 828
    }
829
  }
472 georgesk 830
  else{ /* c'est une réaction redox  */
10 reyssat 831
    o << "E\\,=\\,";
472 georgesk 832
    if(wantedlatex){
833
      w << "E\\,=\\,";
834
    }else{
835
      w << "E=";
836
    }
104 bpr 837
    if (val > MINVAL) {
10 reyssat 838
      o << val;
472 georgesk 839
      w << val << ";";
10 reyssat 840
    }
841
    else{
842
      o << "E_{0}";
472 georgesk 843
      if(wantedlatex){
844
        w << "E_{0};";
845
      }else{
846
        w << "E0;";
847
      }
10 reyssat 848
    }
849
    o << "\\,+\\,\\frac{R\\,T}{";
850
    o << gauche->nbelectron()+droit->nbelectron() << "\\,F}";
851
    o << "\\log";
472 georgesk 852
    w << gauche->nbelectron()+droit->nbelectron() << ";";
104 bpr 853
    if (gauche->redox()){ /* c'est une réduction */
10 reyssat 854
      ga=gauche; dr=droit;
855
    }
856
    else{ /* c'est une oxydation */
857
      ga=droit; dr=gauche;
858
    }
859
    if (dr->printableNernst()){
472 georgesk 860
      o << "\\frac{";
861
      ga->printNernst(o);
862
      o << "}{";
863
      dr->printNernst(o);
864
      o << "}";
865
    }
866
    else {
867
      o << "(";
868
      ga->printNernst(o);
869
      o << ")";
870
    }
871
    // implanter la sortie pour Wims ici.
872
    dr->printNernstWIMS(w,wantedlatex);
873
    w << "; ";
874
    ga->printNernstWIMS(w,wantedlatex);
10 reyssat 875
  }
876
}
877
 
104 bpr 878
std::string Chemeq::valeur_latex()const{
879
  std::ostringstream so;
880
  so << val;
881
  std::string s(so.str());
882
  std::string::size_type epos=s.find('e',0);
883
  if (epos!=std::string::npos){
884
    s.erase(epos,1);
885
    s.insert(epos,"\\times 10^{");
886
    s=s+"}";
887
  }
888
  return (std::string) s;
889
}
890
 
10 reyssat 891
std::ostream & operator << (std::ostream & o, const Chemeq & c){
13121 georgesk 892
  if (c.is_equilibrium()){ /* equilibria must be rendered with two arrows */
893
    o << *c.membregauche() << "\\,\\leftrightharpoons\\," << *c.membredroit();
894
  } else {
895
    o << *c.membregauche() << "\\,\\longrightarrow\\," << *c.membredroit();
896
  }
104 bpr 897
  if (c.valeur() > MINVAL) {
10 reyssat 898
    o << "\\,(";
899
    if (c.constante()!=std::string("")) o << c.constante() << "\\,=\\,";
104 bpr 900
    o << c.valeur_latex();
10 reyssat 901
    if (c.redox()) o << " V";
902
    o << ")";
903
  }
904
  return o;
905
}
906
 
907
std::ostream & operator << (std::ostream & o, fraction f){
908
  o << f.i;
909
  if (f.d!=1) o << '/' << f.d;
910
  return o;
911
}
912
 
913
fraction operator * (fraction f, int m){
914
  fraction result = fraction(f.i*m, f.d);
915
  result.simplifie();
916
  return result;
917
}
918
 
919
fraction operator * (int m, fraction f){
920
  fraction result = fraction(f.i*m, f.d);
921
  result.simplifie();
922
  return result;
923
}
924
 
925
fraction operator * (fraction f, fraction m)
926
{
927
  fraction result = fraction(f.i*m.i, f.d*m.d);
928
  result.simplifie();
929
  return result;
930
}
931
 
932
fraction operator + (fraction f, fraction g){
933
  fraction result = fraction(f.i*g.d+g.i*f.d, f.d*g.d);
934
  result.simplifie();
935
  return result;
936
}
937
 
938
fraction operator - (fraction f, fraction g){
939
  fraction result = fraction(f.i*g.d-g.i*f.d, f.d*g.d);
940
  result.simplifie();
941
  return result;
942
}
943
 
104 bpr 944
const fraction & minFraction(const fraction& f1, const fraction &f2){
945
  if (f1.i*f2.d > f2.i*f1.d) return f1;
946
  else return f2;
947
}
948
 
10 reyssat 949
void fraction::simplifie(){
950
  int maxprem = 23;
951
  int premiers[]={2,3,5,7,11,13,17,19,23,29};
952
  int n;
953
 
954
  for (n=0; premiers[n]<= maxprem; n++){
955
    while (i % premiers[n] == 0 && d % premiers[n] == 0){
956
      i /= premiers[n]; d /= premiers[n];
957
    }
958
  }
959
}
960
 
961
bool operator > (fraction f, int i){
962
  return f.i > f.d*i;
963
}
964
 
965
bool operator > (fraction f1, fraction f2){
966
  return f1.i*f2.d > f1.d*f2.i;
967
}
968
 
969
bool operator != (fraction f, int i){
970
  return f.i != f.d*i;
971
}
972
 
973
double mendelweight(int i){
974
  if (i>=0) return strtod (table[i].info[WEIGHT],0); else return 0.0;
975
}
976
 
977
int findmendel(const char * symb){
978
  int i=0;
979
  while (table[i].info[0] && strcmp(table[i].info[SYMBOL], symb) != 0) i++;
980
  if (table[i].info[0]) return i; else return -1;
981
}
982
 
983
double mendelweight(const char * symb){
984
  int i;
985
  i = findmendel(symb);
986
  return mendelweight(i);
987
}