Subversion Repositories wimsdev

Rev

Rev 104 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
10 reyssat 1
#include "chemeq.h"
2
#include <math.h>
3
#include <sstream>
4
 
5
atome lesatomes[] ={
6
{-1, "e"},
7
{1, "H"},
8
{2, "He"},
9
{3, "Li"},
10
{4, "Be"},
11
{5, "B"},
12
{6, "C"},
13
{7, "N"},
14
{8, "O"},
15
{9, "F"},
16
{10, "Ne"},
17
{11, "Na"},
18
{12, "Mg"},
19
{13, "Al"},
20
{14, "Si"},
21
{15, "P"},
22
{16, "S"},
23
{17, "Cl"},
24
{18, "Ar"},
25
{19, "K"},
26
{20, "Ca"},
27
{21, "Sc"},
28
{22, "Ti"},
29
{23, "V"},
30
{24, "Cr"},
31
{25, "Mn"},
32
{26, "Fe"},
33
{27, "Co"},
34
{28, "Ni"},
35
{29, "Cu"},
36
{30, "Zn"},
37
{31, "Ga"},
38
{32, "Ge"},
39
{33, "As"},
40
{34, "Se"},
41
{35, "Br"},
42
{36, "Kr"},
43
{37, "Rb"},
44
{38, "Sr"},
45
{39, "Y"},
46
{40, "Zr"},
47
{41, "Nb"},
48
{42, "Mo"},
49
{43, "Tc"},
50
{44, "Ru"},
51
{45, "Rh"},
52
{46, "Pd"},
53
{47, "Ag"},
54
{48, "Cd"},
55
{49, "In"},
56
{50, "Sn"},
57
{51, "Sb"},
58
{52, "Te"},
59
{53, "I"},
60
{54, "Xe"},
61
{55, "Cs"},
62
{56, "Ba"},
63
{57, "La"},
64
{58, "Ce"},
65
{59, "Pr"},
66
{60, "Nd"},
67
{61, "Pm"},
68
{62, "Sm"},
69
{63, "Eu"},
70
{64, "Gd"},
71
{65, "Tb"},
72
{66, "Dy"},
73
{67, "Ho"},
74
{68, "Er"},
75
{69, "Tm"},
76
{70, "Yb"},
77
{71, "Lu"},
78
{72, "Hf"},
79
{73, "Ta"},
80
{74, "W"},
81
{75, "Re"},
82
{76, "Os"},
83
{77, "Ir"},
84
{78, "Pt"},
85
{79, "Au"},
86
{80, "Hg"},
87
{81, "Tl"},
88
{82, "Pb"},
89
{83, "Bi"},
90
{84, "Po"},
91
{85, "At"},
92
{86, "Rn"},
93
{87, "Fr"},
94
{88, "Ra"},
95
{89, "Ac"},
96
{90, "Th"},
97
{91, "Pa"},
98
{92, "U"},
99
{93, "Np"},
100
{94, "Pu"},
101
{95, "Am"},
102
{96, "Cm"},
103
{97, "Bk"},
104
{98, "Cf"},
105
{99, "Es"},
106
{100, "Fm"},
107
{101, "Md"},
108
{102, "No"},
109
{103, "Lr"},
110
{104, "Rf"},
111
{105, "Db"},
112
{106, "Sg"},
113
{107, "Bh"},
114
{108, "Hs"},
115
{109, "Mt"},
116
{110, "Uun"},
117
{111, "Uuu"},
118
{112, "Uub"},
119
{113, "Uut"},
120
{114, "Uuq"},
121
{115, "Uup"},
122
{116, "Uuh"},
123
{117, "Uus"},
124
{118, "Uuo"},
125
{0,"fin"}
126
};
127
 
128
std::ostream & Compteur::operator << (std::ostream & o)const{
129
  const_iterator i=begin();
130
  while (i != end()){
131
    o << i->first << " : " << i->second;
132
    if (++i != end()) o << " ";
133
  }
134
  return o;
135
}
136
 
137
std::ostream & operator << (std::ostream & o, const Compteur & c){
138
  return c.operator << (o);
139
}
140
 
141
double AtomeListe::weight(fraction mult)const{
142
  const AtomeListe * al;
143
  double w=0.0;
144
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
145
    w=mendelweight(symb)*nb*mult.i/mult.d;
146
    //debug(); std::cout << std::endl;
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;
157
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
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){
168
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
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;
180
  if(al->Z()!=0){ /* cas où ce n'est pas un groupe */
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
 
195
bool operator == (const AtomeListe & a1, const AtomeListe & a2){
196
  std::stringstream s1, s2;
197
  a1.printnorm(s1);
198
  a2.printnorm(s2);
199
  return s1 == s2;
200
}
201
 
202
void AtomeListe::printcount(std::ostream & o, const fraction& n, int multiple=1) const{
203
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
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 << "[";
215
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
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){
233
    o << l.symbole();
234
  }
235
  else if (l.Z()==-1){ // cas de l'électron
236
    o << "e";
237
  }
238
  else{                // cas des groupes parenthésés
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
 
249
char* moltypeStr[] = { "aq", "g", "s" };
250
 
251
bool operator == (const Molec & m1, const Molec & m2){
252
  return *(m1.al) == *(m2.al) && m1.ch == m2.ch;
253
}
254
 
255
const std::string Molec::signature()const{
256
  std::ostringstream o;
257
  o << liste();
258
  if (charge()){
259
    o << "^{";
260
    if(fabs(1.0*charge())!=1) o << fabs(1.0*charge());
261
    if(charge()>0) o << "+}"; else o << "-}";
262
  }
263
  if (t != aqueous) o << moltypeStr[t];
264
  return std::string (o.str());
265
}
266
 
267
bool Molec::printcount(std::ostream & o, bool first) const{
268
  if (!first) o << ", ";
269
  first=false;
270
  printnorm(o);
271
  o << '|';
272
  al-> printcount(o,nb);
273
  return first;
274
}
275
 
276
bool Molec::printelec(std::ostream & o, bool first) const{
277
  if (!first) o << ", ";
278
  first=false;
279
  printnorm(o);
280
  o << '|';
281
  o << nb << '*' << ch;
282
  return first;
283
}
284
 
285
bool Molec::printspecies(std::ostream & o, bool first) const{
286
  if (!first) o << ", ";
287
  first=false;
288
  printnorm(o);
289
  return first;
290
}
291
 
292
void Molec::printnorm(std::ostream & o)const{
293
  if (nb!=1) o << nb << " ";
294
  al-> printnorm(o);
295
  if (ch) {
296
    o << "^";
297
    if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
298
    if(ch>0) o << "+"; else o << "-";
299
  }
300
  if (!iswater()&&!iselectron()) o << "_" << moltypeStr[t];
301
}
302
 
303
void Molec::coeff( fraction f){
304
  nb.i *= f.i;
305
  nb.d *= f.d;
306
  nb.simplifie();
307
}
308
 
309
bool Molec::printNernst(std::ostream & o, char * prefix){
310
  switch(t){
311
  case sol : return 0;
312
  case aqueous :
313
    if (iswater() || iselectron()) return 0;
314
    o << prefix << "[" << *al;
315
    if (ch){
316
      o << "^{";
317
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
318
      if(ch>0) o << "+}"; else o << "-}";
319
    }
320
    if (t != aqueous) o << "_{" << moltypeStr[t] << "}";
321
    o  <<"]";
322
    if (nb!=1) {
323
      o << "^{";
324
      printNombre(o);
325
      o << "}";
326
    }
327
    return 1;
328
  case gas :
329
    o << prefix << "P_{" << *al << "}";
330
    if (nb!=1) {
331
      o << "^{";
332
      printNombre(o);
333
      o << "}";
334
    }
335
    return 1;
336
  }
337
}
338
 
339
bool Molec::iswater()const{
340
  if (t != aqueous) return 0;
341
  if (signature()==std::string("H_{2}O") ||
342
      signature()==std::string("OH_{2}")) return 1;
343
  else return 0;
344
}
345
 
346
bool Molec::iselectron()const{
347
  return (signature()==std::string("e^{-}"));
348
}
349
 
350
fraction Molec::nbelectron()const{
351
  if (iselectron()) return nb;
352
  else return fraction(0);
353
}
354
 
355
void Molec::printNombre(std::ostream & o)const{
356
  if (nb.d==1){
357
    o << nb.i << "\\,";
358
  }
359
  else {
360
    o << "\\frac{" << nb.i << "}{" << nb.d << "}\\,";
361
  }
362
}
363
 
364
std::ostream & operator << (std::ostream & o, const Molec & m){
365
  if (m.nombre() != 1) m.printNombre(o);
366
  o << m.liste();
367
  if (m.charge()){
368
    o << "^{";
369
    if(fabs(1.0*m.charge())!=1) o << fabs(1.0*m.charge());
370
    if(m.charge()>0) o << "+}"; else o << "-}";
371
  }
372
  if (m.typage() != aqueous) o << "_{" << moltypeStr[m.typage()] << "}";
373
  return o;
374
}
375
 
376
void Membre::compte(Compteur & c)const{
377
  for(int i =0; i < size(); i++){
378
    operator [] (i)->compte(c);
379
  }
380
}
381
 
382
void Membre::numerote(){
383
  for (int i=0; i < size(); i++){
384
    operator [](i)->numero(i);
385
    operator [](i)->liste().numerote();
386
  }
387
}
388
 
389
void Membre::triage(){
390
  int i,j;
391
  for (i=0; i < size(); i++){
392
    operator [](i)->triage();
393
  }
394
  for (i=0; i < size(); i++){
395
    for (j=i+1; j < size(); j++){
396
      if (operator [](i)->signature() > operator [](j)->signature()){
397
        Molec * m = operator [](i);
398
        operator [](i) = operator [](j);
399
        operator [](j) = m;
400
      }
401
    }
402
  }
403
}
404
 
405
void Membre::printcount(std::ostream & o) const{
406
  bool first=true;
407
  for(int i=0; i < size(); i++){
408
    first=operator[](i)->printcount(o,first);
409
  }
410
}
411
 
412
void Membre::printelec(std::ostream & o) const{
413
  bool first=true;
414
  for(int i=0; i < size(); i++){
415
    first=operator[](i)->printelec(o,first);
416
  }
417
}
418
 
419
void Membre::printspecies(std::ostream & o) const{
420
  bool first=true;
421
  for(int i=0; i < size(); i++){
422
    first=operator[](i)->printspecies(o,first);
423
  }
424
}
425
 
426
void Membre::printnorm(std::ostream & o) const{
427
  for(int i=0; i < size(); i++){
428
    operator[](i)->printnorm(o);
429
    if (i < size()-1) o << " + ";
430
  }
431
}
432
 
433
void Membre::printweight(std::ostream & o) const{
434
  for(int i=0; i < size(); i++){
435
    o << operator[](i)->weight();
436
    if (i < size()-1) o << " ";
437
  }
438
}
439
 
440
void Membre::coeff( fraction f){
441
  for (int i=0; i<size(); i++) operator[](i)->coeff(f);
442
}
443
 
444
int Membre::printableNernst(){
445
  int result=0;
446
  for (int i=0; i<size(); i++) {
447
    if (operator[](i)->typage() != sol &&
448
        !operator[](i)->iswater() &&
449
        !operator[](i)->iselectron()) result =1;
450
  }  
451
  return result;
452
}
453
 
454
bool Membre::redox()const{
455
  for (int i=0; i<size(); i++){
456
    if ((*this)[i]->iselectron()) /* c'est un électron */ return 1;
457
  }
458
  return 0;
459
}
460
 
461
fraction  Membre::nbelectron()const{
462
  fraction result(0);
463
 
464
  for(int i = 0; i<size(); i++) result=result+(*this)[i]->nbelectron();
465
  return result;
466
}
467
 
468
void Membre::printNernst(std::ostream & o){
469
  bool printed = 0;
470
  char * prefix="";
471
  for (int i=0; i<size(); i++) {
472
    if (i>0) prefix="\\,";
473
    if (operator[](i)->printNernst(o, prefix)){
474
      printed = 1;
475
    }
476
  }
477
  if (!printed) o << "1";
478
}
479
 
480
std::ostream & operator << (std::ostream & o, const Membre & m){
481
  for(int i=0; i < m.size()-1; i++){
482
    o << *m[i] << "\\,+\\,";
483
  }
484
  o << *m[m.size()-1];
485
  return o;
486
}
487
 
488
Membre operator & (Membre & m1, Membre & m2){
489
  Membre result;
490
  fraction min(1);
491
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
492
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
493
      if (**i == **j){
494
        Molec *m = new Molec(**i);
495
        if ((*i)->nb > (*j)->nb){
496
          min=(*j)->nb;
497
        }else{
498
          min=(*i)->nb;
499
        }
500
        m->nb=min;
501
        result.push_back(m);
502
      }
503
    }
504
  }
505
  return result;
506
}
507
 
508
Membre operator - (Membre & m1, Membre & m2){
509
  Membre result;
510
  fraction diff(1);
511
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
512
    Molec *m = new Molec(**i);
513
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
514
      if (**i == **j){
515
        diff=(*i)->nb - (*j)->nb;
516
        m->nb=diff;
517
      }
518
    }
519
    result.push_back(m);
520
  }
521
  return result;
522
}
523
 
524
void Chemeq::printnorm(std::ostream & o){
525
  gauche->printnorm(o);
526
  o << " -> ";
527
  droit->printnorm(o);
528
  if (val>=0){
529
    o << " (";
530
    if (cste!=std::string("")) o << cste << " = ";
531
    o << val;
532
    if (redox()) o << " V";
533
    o << ")";
534
  }
535
}
536
 
537
void Chemeq::printcount(std::ostream & o) const {
538
  gauche->printcount(o);
539
  o << "; ";
540
  droit->printcount(o);
541
}
542
 
543
void Chemeq::printelec(std::ostream & o) const {
544
  gauche->printelec(o);
545
  o << "; ";
546
  droit->printelec(o);
547
}
548
 
549
void Chemeq::printspecies(std::ostream & o) const {
550
  gauche->printspecies(o);
551
  o << "; ";
552
  droit->printspecies(o);
553
}
554
 
555
void Chemeq::printweight(std::ostream & o) const{
556
  gauche->printweight(o);
557
  o << " ";
558
  droit->printweight(o);
559
}
560
 
561
std::string Chemeq::equilibre(){
562
  std::ostringstream s;
563
  Compteur cpg, cpd;
564
  gauche->compte(cpg);
565
  droit->compte(cpd);
566
  if(cpg==cpd) s << "OK";
567
  else s << "ERROR " << cpg << " / " << cpd;
568
  return std::string(s.str());
569
}
570
 
571
void Chemeq::coeff1(){
572
  fraction mult = gauche->operator[](0)->nombre();
573
  mult.inverse();
574
  gauche->coeff(mult);
575
  droit->coeff(mult);
576
  Membre communs(*gauche & *droit);
577
  if (communs.size()>0){
578
    Membre * g, *d;
579
    g= new Membre(*gauche - communs);
580
    d= new Membre(*droit  - communs);
581
    delete gauche;
582
    delete droit;
583
    gauche=g;
584
    droit =d;
585
  }
586
  if (!redox()){
587
    val = val*mult.i/mult.d;
588
  }
589
}
590
 
591
bool Chemeq::redox()const{
592
  return gauche->redox() || droit->redox();
593
}
594
 
595
void Chemeq::printNernst(std::ostream & o){
596
  Membre * ga, * dr;
597
  if (!redox()){
598
    if (gauche->printableNernst()){
599
      o << "\\frac{";
600
      droit->printNernst(o);
601
      o << "}{";
602
      gauche->printNernst(o);
603
      o << "}";
604
    }
605
    else {
606
      droit->printNernst(o);
607
    }
608
    if (val >=0) {
609
      o << "\\,=\\,";
610
      if (cste!=std::string("")) o << cste << "\\,=\\,";
611
      o << val;
612
    }
613
    else{
614
      o << "\\,=\\,K";
615
    }
616
  }
617
  else{ /* c'est une réaction redox */
618
    o << "E\\,=\\,";
619
    if (val >=0) {
620
      o << val;
621
    }
622
    else{
623
      o << "E_{0}";
624
    }
625
    o << "\\,+\\,\\frac{R\\,T}{";
626
    o << gauche->nbelectron()+droit->nbelectron() << "\\,F}";
627
    o << "\\log";
628
    if (gauche->redox()){ /* c'est une réduction */
629
      ga=gauche; dr=droit;
630
    }
631
    else{ /* c'est une oxydation */
632
      ga=droit; dr=gauche;
633
    }
634
    if (dr->printableNernst()){
635
        o << "\\frac{";
636
        ga->printNernst(o);
637
        o << "}{";
638
        dr->printNernst(o);
639
        o << "}";
640
      }
641
      else {
642
        o << "(";
643
        ga->printNernst(o);
644
        o << ")";
645
      }
646
  }
647
}
648
 
649
std::ostream & operator << (std::ostream & o, const Chemeq & c){
650
  o << *c.membregauche() << "\\,\\rightarrow\\," << *c.membredroit();
651
  if (c.valeur() >=0) {
652
    o << "\\,(";
653
    if (c.constante()!=std::string("")) o << c.constante() << "\\,=\\,";
654
    o << c.valeur();
655
    if (c.redox()) o << " V";
656
    o << ")";
657
  }
658
  return o;
659
}
660
 
661
std::ostream & operator << (std::ostream & o, fraction f){
662
  o << f.i;
663
  if (f.d!=1) o << '/' << f.d;
664
  return o;
665
}
666
 
667
fraction operator * (fraction f, int m){
668
  fraction result = fraction(f.i*m, f.d);
669
  result.simplifie();
670
  return result;
671
}
672
 
673
fraction operator * (int m, fraction f){
674
  fraction result = fraction(f.i*m, f.d);
675
  result.simplifie();
676
  return result;
677
}
678
 
679
fraction operator * (fraction f, fraction m)
680
{
681
  fraction result = fraction(f.i*m.i, f.d*m.d);
682
  result.simplifie();
683
  return result;
684
}
685
 
686
fraction operator + (fraction f, fraction g){
687
  fraction result = fraction(f.i*g.d+g.i*f.d, f.d*g.d);
688
  result.simplifie();
689
  return result;
690
}
691
 
692
fraction operator - (fraction f, fraction g){
693
  fraction result = fraction(f.i*g.d-g.i*f.d, f.d*g.d);
694
  result.simplifie();
695
  return result;
696
}
697
 
698
void fraction::simplifie(){
699
  int maxprem = 23;
700
  int premiers[]={2,3,5,7,11,13,17,19,23,29};
701
  int n;
702
 
703
  for (n=0; premiers[n]<= maxprem; n++){
704
    while (i % premiers[n] == 0 && d % premiers[n] == 0){
705
      i /= premiers[n]; d /= premiers[n];
706
    }
707
  }
708
}
709
 
710
bool operator > (fraction f, int i){
711
  return f.i > f.d*i;
712
}
713
 
714
bool operator > (fraction f1, fraction f2){
715
  return f1.i*f2.d > f1.d*f2.i;
716
}
717
 
718
bool operator != (fraction f, int i){
719
  return f.i != f.d*i;
720
}
721
 
722
double mendelweight(int i){
723
  if (i>=0) return strtod (table[i].info[WEIGHT],0); else return 0.0;
724
}
725
 
726
int findmendel(const char * symb){
727
  int i=0;
728
  while (table[i].info[0] && strcmp(table[i].info[SYMBOL], symb) != 0) i++;
729
  if (table[i].info[0]) return i; else return -1;
730
}
731
 
732
double mendelweight(const char * symb){
733
  int i;
734
  i = findmendel(symb);
735
  return mendelweight(i);
736
}