Subversion Repositories wimsdev

Rev

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