00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef MAX
00020 #define MAX(x,y) (( (x) > (y) ) ? (x) : (y))
00021 #endif
00022
00023 #include "DebyeHuckel.h"
00024 #include "ThermoFactory.h"
00025 #include "WaterProps.h"
00026 #include "PDSS_Water.h"
00027 #include <cstring>
00028 #include <cstdlib>
00029
00030 using namespace std;
00031
00032 namespace Cantera {
00033
00034
00035
00036
00037 DebyeHuckel::DebyeHuckel() :
00038 MolalityVPSSTP(),
00039 m_formDH(DHFORM_DILUTE_LIMIT),
00040 m_formGC(2),
00041 m_IionicMolality(0.0),
00042 m_maxIionicStrength(30.0),
00043 m_useHelgesonFixedForm(false),
00044 m_IionicMolalityStoich(0.0),
00045 m_form_A_Debye(A_DEBYE_CONST),
00046 m_A_Debye(1.172576),
00047 m_B_Debye(3.28640E9),
00048 m_waterSS(0),
00049 m_densWaterSS(1000.),
00050 m_waterProps(0)
00051 {
00052
00053 m_npActCoeff.resize(3);
00054 m_npActCoeff[0] = 0.1127;
00055 m_npActCoeff[1] = -0.01049;
00056 m_npActCoeff[2] = 1.545E-3;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 DebyeHuckel::DebyeHuckel(std::string inputFile, std::string id) :
00068 MolalityVPSSTP(),
00069 m_formDH(DHFORM_DILUTE_LIMIT),
00070 m_formGC(2),
00071 m_IionicMolality(0.0),
00072 m_maxIionicStrength(30.0),
00073 m_useHelgesonFixedForm(false),
00074 m_IionicMolalityStoich(0.0),
00075 m_form_A_Debye(A_DEBYE_CONST),
00076 m_A_Debye(1.172576),
00077 m_B_Debye(3.28640E9),
00078 m_waterSS(0),
00079 m_densWaterSS(1000.),
00080 m_waterProps(0)
00081 {
00082 m_npActCoeff.resize(3);
00083 m_npActCoeff[0] = 0.1127;
00084 m_npActCoeff[1] = -0.01049;
00085 m_npActCoeff[2] = 1.545E-3;
00086 constructPhaseFile(inputFile, id);
00087 }
00088
00089 DebyeHuckel::DebyeHuckel(XML_Node& phaseRoot, std::string id) :
00090 MolalityVPSSTP(),
00091 m_formDH(DHFORM_DILUTE_LIMIT),
00092 m_formGC(2),
00093 m_IionicMolality(0.0),
00094 m_maxIionicStrength(3.0),
00095 m_useHelgesonFixedForm(false),
00096 m_IionicMolalityStoich(0.0),
00097 m_form_A_Debye(A_DEBYE_CONST),
00098 m_A_Debye(1.172576),
00099 m_B_Debye(3.28640E9),
00100 m_waterSS(0),
00101 m_densWaterSS(1000.),
00102 m_waterProps(0)
00103 {
00104 m_npActCoeff.resize(3);
00105 m_npActCoeff[0] = 0.1127;
00106 m_npActCoeff[1] = -0.01049;
00107 m_npActCoeff[2] = 1.545E-3;
00108 constructPhaseXML(phaseRoot, id);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117 DebyeHuckel::DebyeHuckel(const DebyeHuckel &b) :
00118 MolalityVPSSTP(),
00119 m_formDH(DHFORM_DILUTE_LIMIT),
00120 m_formGC(2),
00121 m_IionicMolality(0.0),
00122 m_maxIionicStrength(30.0),
00123 m_useHelgesonFixedForm(false),
00124 m_IionicMolalityStoich(0.0),
00125 m_form_A_Debye(A_DEBYE_CONST),
00126 m_A_Debye(1.172576),
00127 m_B_Debye(3.28640E9),
00128 m_waterSS(0),
00129 m_densWaterSS(1000.),
00130 m_waterProps(0)
00131 {
00132
00133
00134
00135
00136 *this = b;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 DebyeHuckel& DebyeHuckel::
00146 operator=(const DebyeHuckel &b) {
00147 if (&b != this) {
00148 MolalityVPSSTP::operator=(b);
00149 m_formDH = b.m_formDH;
00150 m_formGC = b.m_formGC;
00151 m_Aionic = b.m_Aionic;
00152 m_npActCoeff = b.m_npActCoeff;
00153 m_IionicMolality = b.m_IionicMolality;
00154 m_maxIionicStrength = b.m_maxIionicStrength;
00155 m_useHelgesonFixedForm= b.m_useHelgesonFixedForm;
00156 m_IionicMolalityStoich= b.m_IionicMolalityStoich;
00157 m_form_A_Debye = b.m_form_A_Debye;
00158 m_A_Debye = b.m_A_Debye;
00159 m_B_Debye = b.m_B_Debye;
00160 m_B_Dot = b.m_B_Dot;
00161 m_npActCoeff = b.m_npActCoeff;
00162
00163
00164 m_waterSS = dynamic_cast<PDSS_Water *>(providePDSS(0)) ;
00165 if (!m_waterSS) {
00166 throw CanteraError("DebyHuckel::operator=()", "Dynamic cast to waterPDSS failed");
00167 }
00168
00169 m_densWaterSS = b.m_densWaterSS;
00170
00171 if (m_waterProps) {
00172 delete m_waterProps;
00173 m_waterProps = 0;
00174 }
00175 if (b.m_waterProps) {
00176 m_waterProps = new WaterProps(m_waterSS);
00177 }
00178
00179 m_expg0_RT = b.m_expg0_RT;
00180 m_pe = b.m_pe;
00181 m_pp = b.m_pp;
00182 m_tmpV = b.m_tmpV;
00183 m_speciesCharge_Stoich= b.m_speciesCharge_Stoich;
00184 m_Beta_ij = b.m_Beta_ij;
00185 m_lnActCoeffMolal = b.m_lnActCoeffMolal;
00186 m_d2lnActCoeffMolaldT2= b.m_d2lnActCoeffMolaldT2;
00187 }
00188 return *this;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 DebyeHuckel::~DebyeHuckel() {
00199 if (m_waterProps) {
00200 delete m_waterProps; m_waterProps = 0;
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 ThermoPhase* DebyeHuckel::duplMyselfAsThermoPhase() const {
00212 DebyeHuckel* mtp = new DebyeHuckel(*this);
00213 return (ThermoPhase *) mtp;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 int DebyeHuckel::eosType() const {
00223 int res;
00224 switch (m_formGC) {
00225 case 0:
00226 res = cDebyeHuckel0;
00227 break;
00228 case 1:
00229 res = cDebyeHuckel1;
00230 break;
00231 case 2:
00232 res = cDebyeHuckel2;
00233 break;
00234 default:
00235 throw CanteraError("eosType", "Unknown type");
00236 break;
00237 }
00238 return res;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 doublereal DebyeHuckel::enthalpy_mole() const {
00248 getPartialMolarEnthalpies(DATA_PTR(m_tmpV));
00249 return mean_X(DATA_PTR(m_tmpV));
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 doublereal DebyeHuckel::intEnergy_mole() const {
00259 double hh = enthalpy_mole();
00260 double pres = pressure();
00261 double molarV = 1.0/molarDensity();
00262 double uu = hh - pres * molarV;
00263 return uu;
00264 }
00265
00266
00267
00268
00269
00270
00271 doublereal DebyeHuckel::entropy_mole() const {
00272 getPartialMolarEntropies(DATA_PTR(m_tmpV));
00273 return mean_X(DATA_PTR(m_tmpV));
00274 }
00275
00276
00277 doublereal DebyeHuckel::gibbs_mole() const {
00278 getChemPotentials(DATA_PTR(m_tmpV));
00279 return mean_X(DATA_PTR(m_tmpV));
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 doublereal DebyeHuckel::cp_mole() const {
00289 getPartialMolarCp(DATA_PTR(m_tmpV));
00290 double val = mean_X(DATA_PTR(m_tmpV));
00291 return val;
00292 }
00293
00294
00295 doublereal DebyeHuckel::cv_mole() const {
00296
00297
00298 err("not implemented");
00299 return 0.0;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 doublereal DebyeHuckel::pressure() const {
00312 return m_Pcurrent;
00313 }
00314
00315 void DebyeHuckel::setPressure(doublereal p) {
00316 setState_TP(temperature(), p);
00317 }
00318
00319 void DebyeHuckel::setState_TP(doublereal t, doublereal p) {
00320
00321 State::setTemperature(t);
00322
00323
00324
00325 m_Pcurrent = p;
00326
00327
00328
00329
00330
00331 _updateStandardStateThermo();
00332
00333
00334
00335
00336
00337 calcDensity();
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 void DebyeHuckel::calcDensity() {
00362 if (m_waterSS) {
00363
00364
00365
00366
00367
00368
00369 m_densWaterSS = m_waterSS->density();
00370 }
00371 double *vbar = &m_pp[0];
00372 getPartialMolarVolumes(vbar);
00373 double *x = &m_tmpV[0];
00374 getMoleFractions(x);
00375 doublereal vtotal = 0.0;
00376 for (int i = 0; i < m_kk; i++) {
00377 vtotal += vbar[i] * x[i];
00378 }
00379 doublereal dd = meanMolecularWeight() / vtotal;
00380 State::setDensity(dd);
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 doublereal DebyeHuckel::isothermalCompressibility() const {
00395 throw CanteraError("DebyeHuckel::isothermalCompressibility",
00396 "unimplemented");
00397 return 0.0;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 doublereal DebyeHuckel::thermalExpansionCoeff() const {
00412 throw CanteraError("DebyeHuckel::thermalExpansionCoeff",
00413 "unimplemented");
00414 return 0.0;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 void DebyeHuckel::setDensity(doublereal rho) {
00434 double dens = density();
00435 if (rho != dens) {
00436 throw CanteraError("Idea;MolalSoln::setDensity",
00437 "Density is not an independent variable");
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 void DebyeHuckel::setMolarDensity(const doublereal conc) {
00451 double concI = molarDensity();
00452 if (conc != concI) {
00453 throw CanteraError("Idea;MolalSoln::setMolarDensity",
00454 "molarDensity/density is not an independent variable");
00455 }
00456 }
00457
00458
00459
00460
00461
00462
00463 void DebyeHuckel::setTemperature(const doublereal temp) {
00464 setState_TP(temp, m_Pcurrent);
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 void DebyeHuckel::getActivityConcentrations(doublereal* c) const {
00486 double c_solvent = standardConcentration();
00487 getActivities(c);
00488 for (int k = 0; k < m_kk; k++) {
00489 c[k] *= c_solvent;
00490 }
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 doublereal DebyeHuckel::standardConcentration(int k) const {
00511 double mvSolvent = m_speciesSize[m_indexSolvent];
00512 return 1.0 / mvSolvent;
00513 }
00514
00515
00516
00517
00518
00519 doublereal DebyeHuckel::logStandardConc(int k) const {
00520 double c_solvent = standardConcentration(k);
00521 return log(c_solvent);
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 void DebyeHuckel::getUnitsStandardConc(double *uA, int k, int sizeUA) const {
00547 for (int i = 0; i < sizeUA; i++) {
00548 if (i == 0) uA[0] = 1.0;
00549 if (i == 1) uA[1] = -nDim();
00550 if (i == 2) uA[2] = 0.0;
00551 if (i == 3) uA[3] = 0.0;
00552 if (i == 4) uA[4] = 0.0;
00553 if (i == 5) uA[5] = 0.0;
00554 }
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 void DebyeHuckel::getActivities(doublereal* ac) const {
00566 _updateStandardStateThermo();
00567
00568
00569
00570
00571 s_update_lnMolalityActCoeff();
00572 for (int k = 0; k < m_kk; k++) {
00573 if (k != m_indexSolvent) {
00574 ac[k] = m_molalities[k] * exp(m_lnActCoeffMolal[k]);
00575 }
00576 }
00577 double xmolSolvent = moleFraction(m_indexSolvent);
00578 ac[m_indexSolvent] =
00579 exp(m_lnActCoeffMolal[m_indexSolvent]) * xmolSolvent;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 void DebyeHuckel::
00594 getMolalityActivityCoefficients(doublereal* acMolality) const {
00595 _updateStandardStateThermo();
00596 A_Debye_TP(-1.0, -1.0);
00597 s_update_lnMolalityActCoeff();
00598 copy(m_lnActCoeffMolal.begin(), m_lnActCoeffMolal.end(), acMolality);
00599 for (int k = 0; k < m_kk; k++) {
00600 acMolality[k] = exp(acMolality[k]);
00601 }
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 void DebyeHuckel::getChemPotentials(doublereal* mu) const{
00623 double xx;
00624 const double xxSmall = 1.0E-150;
00625
00626
00627
00628
00629
00630
00631 getStandardChemPotentials(mu);
00632
00633
00634
00635
00636 s_update_lnMolalityActCoeff();
00637
00638
00639
00640 doublereal RT = GasConstant * temperature();
00641 double xmolSolvent = moleFraction(m_indexSolvent);
00642 for (int k = 0; k < m_kk; k++) {
00643 if (m_indexSolvent != k) {
00644 xx = MAX(m_molalities[k], xxSmall);
00645 mu[k] += RT * (log(xx) + m_lnActCoeffMolal[k]);
00646 }
00647 }
00648 xx = MAX(xmolSolvent, xxSmall);
00649 mu[m_indexSolvent] +=
00650 RT * (log(xx) + m_lnActCoeffMolal[m_indexSolvent]);
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 void DebyeHuckel::getPartialMolarEnthalpies(doublereal* hbar) const {
00667
00668
00669
00670 getEnthalpy_RT(hbar);
00671
00672
00673
00674 double T = temperature();
00675 double RT = GasConstant * T;
00676 for (int k = 0; k < m_kk; k++) {
00677 hbar[k] *= RT;
00678 }
00679
00680
00681
00682
00683
00684 double dAdT = dA_DebyedT_TP();
00685 if (dAdT != 0.0) {
00686
00687
00688
00689
00690 s_update_lnMolalityActCoeff();
00691 s_update_dlnMolalityActCoeff_dT();
00692 double RTT = GasConstant * T * T;
00693 for (int k = 0; k < m_kk; k++) {
00694 hbar[k] -= RTT * m_dlnActCoeffMolaldT[k];
00695 }
00696 }
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 void DebyeHuckel::
00729 getPartialMolarEntropies(doublereal* sbar) const {
00730 int k;
00731
00732
00733
00734
00735 getEntropy_R(sbar);
00736
00737
00738
00739 doublereal R = GasConstant;
00740 for (k = 0; k < m_kk; k++) {
00741 sbar[k] *= R;
00742 }
00743
00744
00745
00746
00747 s_update_lnMolalityActCoeff();
00748
00749
00750
00751
00752 doublereal mm;
00753 for (k = 0; k < m_kk; k++) {
00754 if (k != m_indexSolvent) {
00755 mm = fmaxx(SmallNumber, m_molalities[k]);
00756 sbar[k] -= R * (log(mm) + m_lnActCoeffMolal[k]);
00757 }
00758 }
00759 double xmolSolvent = moleFraction(m_indexSolvent);
00760 mm = fmaxx(SmallNumber, xmolSolvent);
00761 sbar[m_indexSolvent] -= R *(log(mm) + m_lnActCoeffMolal[m_indexSolvent]);
00762
00763
00764
00765
00766
00767 double dAdT = dA_DebyedT_TP();
00768 if (dAdT != 0.0) {
00769 s_update_dlnMolalityActCoeff_dT();
00770 double RT = R * temperature();
00771 for (k = 0; k < m_kk; k++) {
00772 sbar[k] -= RT * m_dlnActCoeffMolaldT[k];
00773 }
00774 }
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 void DebyeHuckel::getPartialMolarVolumes(doublereal* vbar) const {
00797 getStandardVolumes(vbar);
00798
00799
00800
00801 s_update_lnMolalityActCoeff();
00802 s_update_dlnMolalityActCoeff_dP();
00803 double T = temperature();
00804 double RT = GasConstant * T;
00805 for (int k = 0; k < m_kk; k++) {
00806 vbar[k] += RT * m_dlnActCoeffMolaldP[k];
00807 }
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 void DebyeHuckel::getPartialMolarCp(doublereal* cpbar) const {
00820
00821
00822
00823
00824 getCp_R(cpbar);
00825
00826 for (int k = 0; k < m_kk; k++) {
00827 cpbar[k] *= GasConstant;
00828 }
00829
00830
00831
00832
00833
00834
00835 double dAdT = dA_DebyedT_TP();
00836 if (dAdT != 0.0) {
00837
00838
00839
00840
00841 s_update_lnMolalityActCoeff();
00842 s_update_dlnMolalityActCoeff_dT();
00843 s_update_d2lnMolalityActCoeff_dT2();
00844 double T = temperature();
00845 double RT = GasConstant * T;
00846 double RTT = RT * T;
00847 for (int k = 0; k < m_kk; k++) {
00848 cpbar[k] -= (2.0 * RT * m_dlnActCoeffMolaldT[k] +
00849 RTT * m_d2lnActCoeffMolaldT2[k]);
00850 }
00851 }
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 void DebyeHuckel::initThermo() {
00868 MolalityVPSSTP::initThermo();
00869 initLengths();
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 void DebyeHuckel::constructPhaseFile(std::string inputFile, std::string id) {
00889
00890 if (inputFile.size() == 0) {
00891 throw CanteraError("DebyeHuckel::initThermo",
00892 "input file is null");
00893 }
00894 std::string path = findInputFile(inputFile);
00895 ifstream fin(path.c_str());
00896 if (!fin) {
00897 throw CanteraError("DebyeHuckel::initThermo","could not open "
00898 +path+" for reading.");
00899 }
00900
00901
00902
00903
00904 XML_Node &phaseNode_XML = xml();
00905 XML_Node *fxml = new XML_Node();
00906 fxml->build(fin);
00907 XML_Node *fxml_phase = findXMLPhase(fxml, id);
00908 if (!fxml_phase) {
00909 throw CanteraError("DebyeHuckel::initThermo",
00910 "ERROR: Can not find phase named " +
00911 id + " in file named " + inputFile);
00912 }
00913 fxml_phase->copy(&phaseNode_XML);
00914 constructPhaseXML(*fxml_phase, id);
00915 delete fxml;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924 static int interp_est(std::string estString) {
00925 const char *cc = estString.c_str();
00926 string lc = lowercase(estString);
00927 const char *ccl = lc.c_str();
00928 if (!strcmp(ccl, "solvent")) {
00929 return cEST_solvent;
00930 } else if (!strcmp(ccl, "chargedspecies")) {
00931 return cEST_chargedSpecies;
00932 } else if (!strcmp(ccl, "weakacidassociated")) {
00933 return cEST_weakAcidAssociated;
00934 } else if (!strcmp(ccl, "strongacidassociated")) {
00935 return cEST_strongAcidAssociated;
00936 } else if (!strcmp(ccl, "polarneutral")) {
00937 return cEST_polarNeutral;
00938 } else if (!strcmp(ccl, "nonpolarneutral")) {
00939 return cEST_nonpolarNeutral;
00940 }
00941 int retn, rval;
00942 if ((retn = sscanf(cc, "%d", &rval)) != 1) {
00943 return -1;
00944 }
00945 return rval;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972 void DebyeHuckel::constructPhaseXML(XML_Node& phaseNode, std::string id) {
00973
00974 if (id.size() > 0) {
00975 std::string idp = phaseNode.id();
00976 if (idp != id) {
00977 throw CanteraError("DebyeHuckel::constructPhaseXML",
00978 "phasenode and Id are incompatible");
00979 }
00980 }
00981
00982
00983
00984
00985 if (!phaseNode.hasChild("thermo")) {
00986 throw CanteraError("DebyeHuckel::constructPhaseXML",
00987 "no thermo XML node");
00988 }
00989 XML_Node& thermoNode = phaseNode.child("thermo");
00990
00991
00992
00993
00994 if (thermoNode.hasChild("standardConc")) {
00995 XML_Node& scNode = thermoNode.child("standardConc");
00996 m_formGC = 2;
00997 std::string formString = scNode.attrib("model");
00998 if (formString != "") {
00999 if (formString == "unity") {
01000 m_formGC = 0;
01001 printf("exit standardConc = unity not done\n");
01002 exit(EXIT_FAILURE);
01003 } else if (formString == "molar_volume") {
01004 m_formGC = 1;
01005 printf("exit standardConc = molar_volume not done\n");
01006 exit(EXIT_FAILURE);
01007 } else if (formString == "solvent_volume") {
01008 m_formGC = 2;
01009 } else {
01010 throw CanteraError("DebyeHuckel::constructPhaseXML",
01011 "Unknown standardConc model: " + formString);
01012 }
01013 }
01014 }
01015
01016
01017
01018
01019 std::string solventName = "";
01020 if (thermoNode.hasChild("solvent")) {
01021 XML_Node& scNode = thermoNode.child("solvent");
01022 vector<std::string> nameSolventa;
01023 getStringArray(scNode, nameSolventa);
01024 int nsp = static_cast<int>(nameSolventa.size());
01025 if (nsp != 1) {
01026 throw CanteraError("DebyeHuckel::constructPhaseXML",
01027 "badly formed solvent XML node");
01028 }
01029 solventName = nameSolventa[0];
01030 }
01031
01032
01033
01034
01035
01036 if (thermoNode.hasChild("activityCoefficients")) {
01037 XML_Node& scNode = thermoNode.child("activityCoefficients");
01038 m_formDH = DHFORM_DILUTE_LIMIT;
01039 std::string formString = scNode.attrib("model");
01040 if (formString != "") {
01041 if (formString == "Dilute_limit") {
01042 m_formDH = DHFORM_DILUTE_LIMIT;
01043 } else if (formString == "Bdot_with_variable_a") {
01044 m_formDH = DHFORM_BDOT_AK ;
01045 } else if (formString == "Bdot_with_common_a") {
01046 m_formDH = DHFORM_BDOT_ACOMMON;
01047 } else if (formString == "Beta_ij") {
01048 m_formDH = DHFORM_BETAIJ;
01049 } else if (formString == "Pitzer_with_Beta_ij") {
01050 m_formDH = DHFORM_PITZER_BETAIJ;
01051 } else {
01052 throw CanteraError("DebyeHuckel::constructPhaseXML",
01053 "Unknown standardConc model: " + formString);
01054 }
01055 }
01056 } else {
01057
01058
01059
01060
01061 m_formDH = DHFORM_DILUTE_LIMIT;
01062 }
01063
01064
01065
01066
01067
01068
01069 bool m_ok = importPhase(phaseNode, this);
01070 if (!m_ok) {
01071 throw CanteraError("DebyeHuckel::constructPhaseXML",
01072 "importPhase failed ");
01073 }
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 void DebyeHuckel::
01095 initThermoXML(XML_Node& phaseNode, std::string id) {
01096 int k;
01097 std::string stemp;
01098
01099
01100
01101 if (!phaseNode.hasChild("thermo")) {
01102 throw CanteraError("HMWSoln::initThermoXML",
01103 "no thermo XML node");
01104 }
01105 XML_Node& thermoNode = phaseNode.child("thermo");
01106
01107
01108
01109
01110 if (thermoNode.hasChild("standardConc")) {
01111 XML_Node& scNode = thermoNode.child("standardConc");
01112 m_formGC = 2;
01113 std::string formString = scNode.attrib("model");
01114 if (formString != "") {
01115 if (formString == "unity") {
01116 m_formGC = 0;
01117 printf("exit standardConc = unity not done\n");
01118 exit(EXIT_FAILURE);
01119 } else if (formString == "molar_volume") {
01120 m_formGC = 1;
01121 printf("exit standardConc = molar_volume not done\n");
01122 exit(EXIT_FAILURE);
01123 } else if (formString == "solvent_volume") {
01124 m_formGC = 2;
01125 } else {
01126 throw CanteraError("DebyeHuckel::constructPhaseXML",
01127 "Unknown standardConc model: " + formString);
01128 }
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141 std::string solventName = "";
01142 if (thermoNode.hasChild("solvent")) {
01143 XML_Node& scNode = thermoNode.child("solvent");
01144 vector<std::string> nameSolventa;
01145 getStringArray(scNode, nameSolventa);
01146 int nsp = static_cast<int>(nameSolventa.size());
01147 if (nsp != 1) {
01148 throw CanteraError("DebyeHuckel::initThermoXML",
01149 "badly formed solvent XML node");
01150 }
01151 solventName = nameSolventa[0];
01152 }
01153 for (k = 0; k < m_kk; k++) {
01154 std::string sname = speciesName(k);
01155 if (solventName == sname) {
01156 m_indexSolvent = k;
01157 break;
01158 }
01159 }
01160 if (m_indexSolvent == -1) {
01161 cout << "DebyeHuckel::initThermoXML: Solvent Name not found"
01162 << endl;
01163 throw CanteraError("DebyeHuckel::initThermoXML",
01164 "Solvent name not found");
01165 }
01166 if (m_indexSolvent != 0) {
01167 throw CanteraError("DebyeHuckel::initThermoXML",
01168 "Solvent " + solventName +
01169 " should be first species");
01170 }
01171
01172
01173
01174
01175
01176 if (thermoNode.hasChild("activityCoefficients")) {
01177 XML_Node& scNode = thermoNode.child("activityCoefficients");
01178 m_formDH = DHFORM_DILUTE_LIMIT;
01179 std::string formString = scNode.attrib("model");
01180 if (formString != "") {
01181 if (formString == "Dilute_limit") {
01182 m_formDH = DHFORM_DILUTE_LIMIT;
01183 } else if (formString == "Bdot_with_variable_a") {
01184 m_formDH = DHFORM_BDOT_AK ;
01185 } else if (formString == "Bdot_with_common_a") {
01186 m_formDH = DHFORM_BDOT_ACOMMON;
01187 } else if (formString == "Beta_ij") {
01188 m_formDH = DHFORM_BETAIJ;
01189 } else if (formString == "Pitzer_with_Beta_ij") {
01190 m_formDH = DHFORM_PITZER_BETAIJ;
01191 } else {
01192 throw CanteraError("DebyeHuckel::constructPhaseXML",
01193 "Unknown standardConc model: " + formString);
01194 }
01195 }
01196 } else {
01197
01198
01199
01200
01201 m_formDH = DHFORM_DILUTE_LIMIT;
01202 }
01203
01204
01205
01206
01207
01208 initThermo();
01209
01210
01211
01212
01213
01214
01215 XML_Node& speciesList = phaseNode.child("speciesArray");
01216 XML_Node* speciesDB =
01217 get_XML_NameID("speciesData", speciesList["datasrc"],
01218 &phaseNode.root());
01219 const vector<string>&sss = speciesNames();
01220
01221 for (k = 0; k < m_kk; k++) {
01222 XML_Node* s = speciesDB->findByAttr("name", sss[k]);
01223 if (!s) {
01224 throw CanteraError("DebyeHuckel::initThermoXML",
01225 "Species Data Base " + sss[k] + " not found");
01226 }
01227 XML_Node *ss = s->findByName("standardState");
01228 if (!ss) {
01229 throw CanteraError("DebyeHuckel::initThermoXML",
01230 "Species " + sss[k] +
01231 " standardState XML block not found");
01232 }
01233 std::string modelStringa = ss->attrib("model");
01234 if (modelStringa == "") {
01235 throw CanteraError("DebyeHuckel::initThermoXML",
01236 "Species " + sss[k] +
01237 " standardState XML block model attribute not found");
01238 }
01239 std::string modelString = lowercase(modelStringa);
01240
01241 if (k == 0) {
01242 if (modelString == "wateriapws" || modelString == "real_water" ||
01243 modelString == "waterpdss") {
01244
01245
01246
01247 m_waterSS = dynamic_cast<PDSS_Water *>(providePDSS(0)) ;
01248 if (!m_waterSS) {
01249 throw CanteraError("HMWSoln::installThermoXML",
01250 "Dynamic cast to PDSS_Water failed");
01251 }
01252
01253
01254
01255
01256
01257 m_waterSS->setState_TP(300., OneAtm);
01258 double dens = m_waterSS->density();
01259 double mw = m_waterSS->molecularWeight();
01260 m_speciesSize[0] = mw / dens;
01261 #ifdef DEBUG_MODE_NOT
01262 cout << "Solvent species " << sss[k] << " has volume " <<
01263 m_speciesSize[k] << endl;
01264 #endif
01265 } else if (modelString == "constant_incompressible") {
01266 m_speciesSize[k] = getFloat(*ss, "molarVolume", "toSi");
01267 #ifdef DEBUG_MODE_NOT
01268 cout << "species " << sss[k] << " has volume " <<
01269 m_speciesSize[k] << endl;
01270 #endif
01271 } else {
01272 throw CanteraError("DebyeHuckel::initThermoXML",
01273 "Solvent SS Model \"" + modelStringa +
01274 "\" is not known");
01275 }
01276 } else {
01277 if (modelString != "constant_incompressible") {
01278 throw CanteraError("DebyeHuckel::initThermoXML",
01279 "Solute SS Model \"" + modelStringa +
01280 "\" is not known");
01281 }
01282 m_speciesSize[k] = getFloat(*ss, "molarVolume", "toSI");
01283 #ifdef DEBUG_MODE_NOT
01284 cout << "species " << sss[k] << " has volume " <<
01285 m_speciesSize[k] << endl;
01286 #endif
01287 }
01288
01289 }
01290
01291
01292
01293
01294
01295 XML_Node *acNodePtr = 0;
01296 if (thermoNode.hasChild("activityCoefficients")) {
01297 XML_Node& acNode = thermoNode.child("activityCoefficients");
01298 acNodePtr = &acNode;
01299
01300
01301
01302 if (acNode.hasChild("A_Debye")) {
01303 XML_Node *ss = acNode.findByName("A_Debye");
01304 string modelStringa = ss->attrib("model");
01305 string modelString = lowercase(modelStringa);
01306 if (modelString != "") {
01307 if (modelString == "water") {
01308 m_form_A_Debye = A_DEBYE_WATER;
01309 } else {
01310 throw CanteraError("DebyeHuckel::initThermoXML",
01311 "A_Debye Model \"" + modelStringa +
01312 "\" is not known");
01313 }
01314 } else {
01315 m_A_Debye = getFloat(acNode, "A_Debye");
01316 #ifdef DEBUG_HKM_NOT
01317 cout << "A_Debye = " << m_A_Debye << endl;
01318 #endif
01319 }
01320 }
01321
01322
01323
01324
01325
01326 if (m_form_A_Debye == A_DEBYE_WATER) {
01327 if (m_waterProps) delete m_waterProps;
01328 m_waterProps = new WaterProps(m_waterSS);
01329 }
01330
01331
01332
01333
01334 if (acNode.hasChild("B_Debye")) {
01335 m_B_Debye = getFloat(acNode, "B_Debye");
01336 #ifdef DEBUG_HKM_NOT
01337 cout << "B_Debye = " << m_B_Debye << endl;
01338 #endif
01339 }
01340
01341
01342
01343
01344 if (acNode.hasChild("B_dot")) {
01345 if (m_formDH == DHFORM_BETAIJ ||
01346 m_formDH == DHFORM_DILUTE_LIMIT ||
01347 m_formDH == DHFORM_PITZER_BETAIJ) {
01348 throw CanteraError("DebyeHuckel:init",
01349 "B_dot entry in the wrong DH form");
01350 }
01351 double bdot_common = getFloat(acNode, "B_dot");
01352 #ifdef DEBUG_HKM_NOT
01353 cout << "B_dot = " << bdot_common << endl;
01354 #endif
01355
01356
01357
01358 for (int k = 0; k < m_kk; k++) {
01359 double z_k = charge(k);
01360 if (fabs (z_k) > 0.0001) {
01361 m_B_Dot[k] = bdot_common;
01362 } else {
01363 m_B_Dot[k] = 0.0;
01364 }
01365 }
01366 }
01367
01368
01369
01370
01371 if (acNode.hasChild("maxIonicStrength")) {
01372 m_maxIionicStrength = getFloat(acNode, "maxIonicStrength");
01373 #ifdef DEBUG_HKM_NOT
01374 cout << "m_maxIionicStrength = "
01375 <<m_maxIionicStrength << endl;
01376 #endif
01377 }
01378
01379
01380
01381
01382 if (acNode.hasChild("UseHelgesonFixedForm")) {
01383 m_useHelgesonFixedForm = true;
01384 } else {
01385 m_useHelgesonFixedForm = false;
01386 }
01387
01388
01389
01390
01391 if (acNode.hasChild("ionicRadius")) {
01392 XML_Node& irNode = acNode.child("ionicRadius");
01393
01394 std::string Aunits = "";
01395 double Afactor = 1.0;
01396 if (irNode.hasAttrib("units")) {
01397 std::string Aunits = irNode.attrib("units");
01398 Afactor = toSI(Aunits);
01399 }
01400
01401 if (irNode.hasAttrib("default")) {
01402 std::string ads = irNode.attrib("default");
01403 double ad = fpValue(ads);
01404 for (int k = 0; k < m_kk; k++) {
01405 m_Aionic[k] = ad * Afactor;
01406 }
01407 }
01408
01409
01410
01411
01412
01413
01414
01415
01416 if (m_formDH == DHFORM_BDOT_AK) {
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427 map<string, string> m;
01428 getMap(irNode, m);
01429
01430
01431
01432
01433
01434
01435
01436 map<std::string,std::string>::const_iterator _b = m.begin();
01437 for (; _b != m.end(); ++_b) {
01438 int kk = speciesIndex(_b->first);
01439 if (kk < 0) {
01440
01441
01442
01443
01444 } else {
01445 m_Aionic[kk] = fpValue(_b->second) * Afactor;
01446 }
01447 }
01448 }
01449 }
01450
01451
01452
01453
01454
01455
01456 if (acNode.hasChild("DHBetaMatrix")) {
01457 if (m_formDH == DHFORM_BETAIJ ||
01458 m_formDH == DHFORM_PITZER_BETAIJ) {
01459 XML_Node& irNode = acNode.child("DHBetaMatrix");
01460 const vector<string>& sn = speciesNames();
01461 getMatrixValues(irNode, sn, sn, m_Beta_ij, true, true);
01462 } else {
01463 throw CanteraError("DebyeHuckel::initThermoXML:",
01464 "DHBetaMatrix found for wrong type");
01465 }
01466 }
01467
01468
01469
01470
01471
01472
01473
01474
01475 m_speciesCharge_Stoich.resize(m_kk, 0.0);
01476 for (k = 0; k < m_kk; k++) {
01477 m_speciesCharge_Stoich[k] = m_speciesCharge[k];
01478 }
01479
01480
01481
01482
01483
01484 std::vector<const XML_Node *> xspecies= speciesData();
01485 std::string kname, jname;
01486 int jj = xspecies.size();
01487 for (k = 0; k < m_kk; k++) {
01488 int jmap = -1;
01489 kname = speciesName(k);
01490 for (int j = 0; j < jj; j++) {
01491 const XML_Node& sp = *xspecies[j];
01492 jname = sp["name"];
01493 if (jname == kname) {
01494 jmap = j;
01495 break;
01496 }
01497 }
01498 if (jmap > -1) {
01499 const XML_Node& sp = *xspecies[jmap];
01500 if (sp.hasChild("stoichIsMods")) {
01501 double val = getFloat(sp, "stoichIsMods");
01502 m_speciesCharge_Stoich[k] = val;
01503 }
01504 }
01505 }
01506
01507
01508
01509
01510 if (acNodePtr) {
01511 if (acNodePtr->hasChild("stoichIsMods")) {
01512 XML_Node& sIsNode = acNodePtr->child("stoichIsMods");
01513
01514 map<std::string, std::string> msIs;
01515 getMap(sIsNode, msIs);
01516 map<std::string,std::string>::const_iterator _b = msIs.begin();
01517 for (; _b != msIs.end(); ++_b) {
01518 int kk = speciesIndex(_b->first);
01519 if (kk < 0) {
01520
01521
01522
01523
01524 } else {
01525 double val = fpValue(_b->second);
01526 m_speciesCharge_Stoich[kk] = val;
01527 }
01528 }
01529 }
01530 }
01531 }
01532
01533
01534
01535
01536
01537
01538
01539
01540 for (k = 0; k < m_kk; k++) {
01541 if (fabs(m_speciesCharge[k]) > 0.0001) {
01542 m_electrolyteSpeciesType[k] = cEST_chargedSpecies;
01543 if (fabs(m_speciesCharge_Stoich[k] - m_speciesCharge[k])
01544 > 0.0001) {
01545 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
01546 }
01547 } else if (fabs(m_speciesCharge_Stoich[k]) > 0.0001) {
01548 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
01549 } else {
01550 m_electrolyteSpeciesType[k] = cEST_nonpolarNeutral;
01551 }
01552 }
01553 m_electrolyteSpeciesType[m_indexSolvent] = cEST_solvent;
01554
01555
01556
01557
01558
01559 std::vector<const XML_Node *> xspecies= speciesData();
01560 const XML_Node *spPtr = 0;
01561 std::string kname;
01562 for (k = 0; k < m_kk; k++) {
01563 kname = speciesName(k);
01564 spPtr = xspecies[k];
01565 if (!spPtr) {
01566 if (spPtr->hasChild("electrolyteSpeciesType")) {
01567 std::string est = getChildValue(*spPtr, "electrolyteSpeciesType");
01568 if ((m_electrolyteSpeciesType[k] = interp_est(est)) == -1) {
01569 throw CanteraError("DebyeHuckel:initThermoXML",
01570 "Bad electrolyte type: " + est);
01571 }
01572 }
01573 }
01574 }
01575
01576
01577
01578 if (acNodePtr) {
01579 if (acNodePtr->hasChild("electrolyteSpeciesType")) {
01580 XML_Node& ESTNode = acNodePtr->child("electrolyteSpeciesType");
01581 map<std::string, std::string> msEST;
01582 getMap(ESTNode, msEST);
01583 map<std::string,std::string>::const_iterator _b = msEST.begin();
01584 for (; _b != msEST.end(); ++_b) {
01585 int kk = speciesIndex(_b->first);
01586 if (kk < 0) {
01587 } else {
01588 std::string est = _b->second;
01589 if ((m_electrolyteSpeciesType[kk] = interp_est(est)) == -1) {
01590 throw CanteraError("DebyeHuckel:initThermoXML",
01591 "Bad electrolyte type: " + est);
01592 }
01593 }
01594 }
01595 }
01596 }
01597
01598
01599
01600
01601
01602
01603 if (phaseNode.hasChild("state")) {
01604 XML_Node& stateNode = phaseNode.child("state");
01605 setStateFromXML(stateNode);
01606 }
01607
01608 }
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618 void DebyeHuckel::setParameters(int n, doublereal* const c) {
01619 }
01620
01621 void DebyeHuckel::getParameters(int &n, doublereal * const c) const {
01622 }
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638 void DebyeHuckel::setParametersFromXML(const XML_Node& eosdata) {
01639 }
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 double DebyeHuckel::A_Debye_TP(double tempArg, double presArg) const {
01662 double T = temperature();
01663 double A;
01664 if (tempArg != -1.0) {
01665 T = tempArg;
01666 }
01667 double P = pressure();
01668 if (presArg != -1.0) {
01669 P = presArg;
01670 }
01671
01672 switch (m_form_A_Debye) {
01673 case A_DEBYE_CONST:
01674 A = m_A_Debye;
01675 break;
01676 case A_DEBYE_WATER:
01677 A = m_waterProps->ADebye(T, P, 0);
01678 m_A_Debye = A;
01679 break;
01680 default:
01681 printf("shouldn't be here\n");
01682 exit(EXIT_FAILURE);
01683 }
01684 return A;
01685 }
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697 double DebyeHuckel::dA_DebyedT_TP(double tempArg, double presArg) const {
01698 double T = temperature();
01699 if (tempArg != -1.0) {
01700 T = tempArg;
01701 }
01702 double P = pressure();
01703 if (presArg != -1.0) {
01704 P = presArg;
01705 }
01706 double dAdT;
01707 switch (m_form_A_Debye) {
01708 case A_DEBYE_CONST:
01709 dAdT = 0.0;
01710 break;
01711 case A_DEBYE_WATER:
01712 dAdT = m_waterProps->ADebye(T, P, 1);
01713 break;
01714 default:
01715 printf("shouldn't be here\n");
01716 exit(EXIT_FAILURE);
01717 }
01718 return dAdT;
01719 }
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 double DebyeHuckel::d2A_DebyedT2_TP(double tempArg, double presArg) const {
01732 double T = temperature();
01733 if (tempArg != -1.0) {
01734 T = tempArg;
01735 }
01736 double P = pressure();
01737 if (presArg != -1.0) {
01738 P = presArg;
01739 }
01740 double d2AdT2;
01741 switch (m_form_A_Debye) {
01742 case A_DEBYE_CONST:
01743 d2AdT2 = 0.0;
01744 break;
01745 case A_DEBYE_WATER:
01746 d2AdT2 = m_waterProps->ADebye(T, P, 2);
01747 break;
01748 default:
01749 printf("shouldn't be here\n");
01750 exit(EXIT_FAILURE);
01751 }
01752 return d2AdT2;
01753 }
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765 double DebyeHuckel::dA_DebyedP_TP(double tempArg, double presArg) const {
01766 double T = temperature();
01767 if (tempArg != -1.0) {
01768 T = tempArg;
01769 }
01770 double P = pressure();
01771 if (presArg != -1.0) {
01772 P = presArg;
01773 }
01774 double dAdP;
01775 switch (m_form_A_Debye) {
01776 case A_DEBYE_CONST:
01777 dAdP = 0.0;
01778 break;
01779 case A_DEBYE_WATER:
01780 dAdP = m_waterProps->ADebye(T, P, 3);
01781 break;
01782 default:
01783 printf("shouldn't be here\n");
01784 exit(EXIT_FAILURE);
01785 }
01786 return dAdP;
01787 }
01788
01789
01790
01791
01792
01793
01794
01795
01796 double DebyeHuckel::AionicRadius(int k) const {
01797 return m_Aionic[k];
01798 }
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808 doublereal DebyeHuckel::err(std::string msg) const {
01809 throw CanteraError("DebyeHuckel",
01810 "Unfinished func called: " + msg );
01811 return 0.0;
01812 }
01813
01814
01815
01816
01817
01818
01819
01820
01821 void DebyeHuckel::initLengths() {
01822 m_kk = nSpecies();
01823
01824
01825
01826
01827
01828 int leng = m_kk;
01829 m_electrolyteSpeciesType.resize(m_kk, cEST_polarNeutral);
01830 m_speciesSize.resize(leng);
01831 m_Aionic.resize(leng, 0.0);
01832 m_lnActCoeffMolal.resize(leng, 0.0);
01833 m_dlnActCoeffMolaldT.resize(leng, 0.0);
01834 m_d2lnActCoeffMolaldT2.resize(leng, 0.0);
01835 m_dlnActCoeffMolaldP.resize(leng, 0.0);
01836 m_B_Dot.resize(leng, 0.0);
01837 m_expg0_RT.resize(leng, 0.0);
01838 m_pe.resize(leng, 0.0);
01839 m_pp.resize(leng, 0.0);
01840 m_tmpV.resize(leng, 0.0);
01841 if (m_formDH == DHFORM_BETAIJ ||
01842 m_formDH == DHFORM_PITZER_BETAIJ) {
01843 m_Beta_ij.resize(leng, leng, 0.0);
01844 }
01845 }
01846
01847
01848
01849
01850
01851
01852
01853
01854 double DebyeHuckel::_nonpolarActCoeff(double IionicMolality) const {
01855 double I2 = IionicMolality * IionicMolality;
01856 double l10actCoeff =
01857 m_npActCoeff[0] * IionicMolality +
01858 m_npActCoeff[1] * I2 +
01859 m_npActCoeff[2] * I2 * IionicMolality;
01860 return pow(10.0 , l10actCoeff);
01861 }
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871 double DebyeHuckel::
01872 _osmoticCoeffHelgesonFixedForm() const {
01873 const double a0 = 1.454;
01874 const double b0 = 0.02236;
01875 const double c0 = 9.380E-3;
01876 const double d0 = -5.362E-4;
01877 double Is = m_IionicMolalityStoich;
01878 if (Is <= 0.0) {
01879 return 0.0;
01880 }
01881 double Is2 = Is * Is;
01882 double bhat = 1.0 + a0 * sqrt(Is);
01883 double func = bhat - 2.0 * log(bhat) - 1.0/bhat;
01884 double v1 = m_A_Debye / (a0 * a0 * a0 * Is) * func;
01885 double oc = 1.0 - v1 + b0 * Is / 2.0 + 2.0 * c0 * Is2 / 3.0
01886 + 3.0 * d0 * Is2 * Is / 4.0;
01887 return oc;
01888 }
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899 double DebyeHuckel::
01900 _lnactivityWaterHelgesonFixedForm() const {
01901
01902
01903
01904 calcMolalities();
01905 double oc = _osmoticCoeffHelgesonFixedForm();
01906 double sum = 0.0;
01907 for (int k = 0; k < m_kk; k++) {
01908 if (k != m_indexSolvent) {
01909 sum += MAX(m_molalities[k], 0.0);
01910 }
01911 }
01912 if (sum > 2.0 * m_maxIionicStrength) {
01913 sum = 2.0 * m_maxIionicStrength;
01914 };
01915 double lac = - m_Mnaught * sum * oc;
01916 return lac;
01917 }
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932 void DebyeHuckel::s_update_lnMolalityActCoeff() const {
01933 double z_k, zs_k1, zs_k2;
01934
01935
01936
01937 calcMolalities();
01938
01939
01940
01941
01942
01943
01944
01945 m_IionicMolality = 0.0;
01946 for (int k = 0; k < m_kk; k++) {
01947 z_k = m_speciesCharge[k];
01948 m_IionicMolality += m_molalities[k] * z_k * z_k;
01949 }
01950 m_IionicMolality /= 2.0;
01951
01952 if (m_IionicMolality > m_maxIionicStrength) {
01953 m_IionicMolality = m_maxIionicStrength;
01954 }
01955
01956
01957
01958
01959 m_IionicMolalityStoich = 0.0;
01960 for (int k = 0; k < m_kk; k++) {
01961 z_k = m_speciesCharge[k];
01962 zs_k1 = m_speciesCharge_Stoich[k];
01963 if (z_k == zs_k1) {
01964 m_IionicMolalityStoich += m_molalities[k] * z_k * z_k;
01965 } else {
01966 zs_k2 = z_k - zs_k1;
01967 m_IionicMolalityStoich
01968 += m_molalities[k] * (zs_k1 * zs_k1 + zs_k2 * zs_k2);
01969 }
01970 }
01971 m_IionicMolalityStoich /= 2.0;
01972
01973 if (m_IionicMolalityStoich > m_maxIionicStrength) {
01974 m_IionicMolalityStoich = m_maxIionicStrength;
01975 }
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986 m_A_Debye = A_Debye_TP();
01987
01988
01989
01990
01991
01992 double xmolSolvent = moleFraction(m_indexSolvent);
01993 xmolSolvent = MAX(8.689E-3, xmolSolvent);
01994
01995 int est;
01996 double ac_nonPolar = 1.0;
01997 double numTmp = m_A_Debye * sqrt(m_IionicMolality);
01998 double denomTmp = m_B_Debye * sqrt(m_IionicMolality);
01999 double coeff;
02000 double lnActivitySolvent = 0.0;
02001 double tmp;
02002 double tmpLn;
02003 double y, yp1, sigma;
02004 switch (m_formDH) {
02005 case DHFORM_DILUTE_LIMIT:
02006 for (int k = 0; k < m_kk; k++) {
02007 z_k = m_speciesCharge[k];
02008 m_lnActCoeffMolal[k] = - z_k * z_k * numTmp;
02009 }
02010 lnActivitySolvent =
02011 (xmolSolvent - 1.0)/xmolSolvent +
02012 2.0 / 3.0 * m_A_Debye * m_Mnaught *
02013 m_IionicMolality * sqrt(m_IionicMolality);
02014 break;
02015
02016 case DHFORM_BDOT_AK:
02017 ac_nonPolar = _nonpolarActCoeff(m_IionicMolality);
02018 for (int k = 0; k < m_kk; k++) {
02019 est = m_electrolyteSpeciesType[k];
02020 if (est == cEST_nonpolarNeutral) {
02021 m_lnActCoeffMolal[k] = log(ac_nonPolar);
02022 } else {
02023 z_k = m_speciesCharge[k];
02024 m_lnActCoeffMolal[k] =
02025 - z_k * z_k * numTmp / (1.0 + denomTmp * m_Aionic[k])
02026 + log(10.0) * m_B_Dot[k] * m_IionicMolality;
02027 }
02028 }
02029
02030 lnActivitySolvent = (xmolSolvent - 1.0)/xmolSolvent;
02031 coeff = 2.0 / 3.0 * m_A_Debye * m_Mnaught
02032 * sqrt(m_IionicMolality);
02033 tmp = 0.0;
02034 if (denomTmp > 0.0) {
02035 for (int k = 0; k < m_kk; k++) {
02036 if (k != m_indexSolvent || m_Aionic[k] != 0.0) {
02037 y = denomTmp * m_Aionic[k];
02038 yp1 = y + 1.0;
02039 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02040 z_k = m_speciesCharge[k];
02041 tmp += m_molalities[k] * z_k * z_k * sigma / 2.0;
02042 }
02043 }
02044 }
02045 lnActivitySolvent += coeff * tmp;
02046 tmp = 0.0;
02047 for (int k = 0; k < m_kk; k++) {
02048 z_k = m_speciesCharge[k];
02049 if ((k != m_indexSolvent) && (z_k != 0.0)) {
02050 tmp += m_B_Dot[k] * m_molalities[k];
02051 }
02052 }
02053 lnActivitySolvent -=
02054 m_Mnaught * log(10.0) * m_IionicMolality * tmp / 2.0;
02055
02056
02057
02058
02059
02060 if (m_useHelgesonFixedForm) {
02061 lnActivitySolvent = _lnactivityWaterHelgesonFixedForm();
02062 }
02063 break;
02064
02065 case DHFORM_BDOT_ACOMMON:
02066 denomTmp *= m_Aionic[0];
02067 for (int k = 0; k < m_kk; k++) {
02068 z_k = m_speciesCharge[k];
02069 m_lnActCoeffMolal[k] =
02070 - z_k * z_k * numTmp / (1.0 + denomTmp)
02071 + log(10.0) * m_B_Dot[k] * m_IionicMolality;
02072 }
02073 if (denomTmp > 0.0) {
02074 y = denomTmp;
02075 yp1 = y + 1.0;
02076 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02077 } else {
02078 sigma = 0.0;
02079 }
02080 lnActivitySolvent =
02081 (xmolSolvent - 1.0)/xmolSolvent +
02082 2.0 /3.0 * m_A_Debye * m_Mnaught *
02083 m_IionicMolality * sqrt(m_IionicMolality) * sigma;
02084 tmp = 0.0;
02085 for (int k = 0; k < m_kk; k++) {
02086 z_k = m_speciesCharge[k];
02087 if ((k != m_indexSolvent) && (z_k != 0.0)) {
02088 tmp += m_B_Dot[k] * m_molalities[k];
02089 }
02090 }
02091 lnActivitySolvent -=
02092 m_Mnaught * log(10.0) * m_IionicMolality * tmp / 2.0;
02093
02094 break;
02095
02096 case DHFORM_BETAIJ:
02097 denomTmp = m_B_Debye * m_Aionic[0];
02098 denomTmp *= sqrt(m_IionicMolality);
02099 lnActivitySolvent =
02100 (xmolSolvent - 1.0)/xmolSolvent;
02101
02102 for (int k = 0; k < m_kk; k++) {
02103 if (k != m_indexSolvent) {
02104 z_k = m_speciesCharge[k];
02105 m_lnActCoeffMolal[k] =
02106 - z_k * z_k * numTmp / (1.0 + denomTmp);
02107 for (int j = 0; j < m_kk; j++) {
02108 double beta = m_Beta_ij.value(k, j);
02109 #ifdef DEBUG_HKM_NOT
02110 if (beta != 0.0) {
02111 printf("b: k = %d, j = %d, betakj = %g\n",
02112 k, j, beta);
02113 }
02114 #endif
02115 m_lnActCoeffMolal[k] += 2.0 * m_molalities[j] * beta;
02116 }
02117 }
02118 }
02119 if (denomTmp > 0.0) {
02120 y = denomTmp;
02121 yp1 = y + 1.0;
02122 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 -2.0*log(yp1));
02123 } else {
02124 sigma = 0.0;
02125 }
02126 lnActivitySolvent =
02127 (xmolSolvent - 1.0)/xmolSolvent +
02128 2.0 /3.0 * m_A_Debye * m_Mnaught *
02129 m_IionicMolality * sqrt(m_IionicMolality) * sigma;
02130 tmp = 0.0;
02131 for (int k = 0; k < m_kk; k++) {
02132 for (int j = 0; j < m_kk; j++) {
02133 tmp +=
02134 m_Beta_ij.value(k, j) * m_molalities[k] * m_molalities[j];
02135 }
02136 }
02137 lnActivitySolvent -= m_Mnaught * tmp;
02138 break;
02139
02140 case DHFORM_PITZER_BETAIJ:
02141 denomTmp = m_B_Debye * sqrt(m_IionicMolality);
02142 denomTmp *= m_Aionic[0];
02143 numTmp = m_A_Debye * sqrt(m_IionicMolality);
02144 tmpLn = log(1.0 + denomTmp);
02145 for (int k = 0; k < m_kk; k++) {
02146 if (k != m_indexSolvent) {
02147 z_k = m_speciesCharge[k];
02148 m_lnActCoeffMolal[k] =
02149 - z_k * z_k * numTmp / 3.0 / (1.0 + denomTmp);
02150 m_lnActCoeffMolal[k] +=
02151 - 2.0 * z_k * z_k * m_A_Debye * tmpLn /
02152 (3.0 * m_B_Debye * m_Aionic[0]);
02153 for (int j = 0; j < m_kk; j++) {
02154 m_lnActCoeffMolal[k] += 2.0 * m_molalities[j] *
02155 m_Beta_ij.value(k, j);
02156 }
02157 }
02158 }
02159 sigma = 1.0 / (1.0 + denomTmp);
02160 lnActivitySolvent =
02161 (xmolSolvent - 1.0)/xmolSolvent +
02162 2.0 /3.0 * m_A_Debye * m_Mnaught *
02163 m_IionicMolality * sqrt(m_IionicMolality) * sigma;
02164 tmp = 0.0;
02165 for (int k = 0; k < m_kk; k++) {
02166 for (int j = 0; j < m_kk; j++) {
02167 tmp +=
02168 m_Beta_ij.value(k, j) * m_molalities[k] * m_molalities[j];
02169 }
02170 }
02171 lnActivitySolvent -= m_Mnaught * tmp;
02172 break;
02173
02174 default:
02175 printf("ERROR\n");
02176 exit(EXIT_FAILURE);
02177 }
02178
02179
02180
02181
02182
02183
02184 xmolSolvent = moleFraction(m_indexSolvent);
02185 m_lnActCoeffMolal[m_indexSolvent] =
02186 lnActivitySolvent - log(xmolSolvent);
02187 }
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201 void DebyeHuckel::s_update_dlnMolalityActCoeff_dT() const {
02202 double z_k, coeff, tmp, y, yp1, sigma, tmpLn;
02203 int k;
02204
02205 double dAdT = dA_DebyedT_TP();
02206 if (dAdT == 0.0) {
02207 for (k = 0; k < m_kk; k++) {
02208 m_dlnActCoeffMolaldT[k] = 0.0;
02209 }
02210 return;
02211 }
02212
02213
02214
02215
02216 double xmolSolvent = moleFraction(m_indexSolvent);
02217 xmolSolvent = MAX(8.689E-3, xmolSolvent);
02218
02219
02220 double sqrtI = sqrt(m_IionicMolality);
02221 double numdAdTTmp = dAdT * sqrtI;
02222 double denomTmp = m_B_Debye * sqrtI;
02223 double d_lnActivitySolvent_dT = 0;
02224
02225 switch (m_formDH) {
02226 case DHFORM_DILUTE_LIMIT:
02227 for (int k = 1; k < m_kk; k++) {
02228 m_dlnActCoeffMolaldT[k] =
02229 m_lnActCoeffMolal[k] * dAdT / m_A_Debye;
02230 }
02231 d_lnActivitySolvent_dT = 2.0 / 3.0 * dAdT * m_Mnaught *
02232 m_IionicMolality * sqrt(m_IionicMolality);
02233 m_dlnActCoeffMolaldT[m_indexSolvent] = d_lnActivitySolvent_dT;
02234 break;
02235
02236 case DHFORM_BDOT_AK:
02237 for (int k = 0; k < m_kk; k++) {
02238 z_k = m_speciesCharge[k];
02239 m_dlnActCoeffMolaldT[k] =
02240 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp * m_Aionic[k]);
02241 }
02242
02243 m_dlnActCoeffMolaldT[m_indexSolvent] = 0.0;
02244
02245 coeff = 2.0 / 3.0 * dAdT * m_Mnaught * sqrtI;
02246 tmp = 0.0;
02247 if (denomTmp > 0.0) {
02248 for (int k = 0; k < m_kk; k++) {
02249 y = denomTmp * m_Aionic[k];
02250 yp1 = y + 1.0;
02251 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02252 z_k = m_speciesCharge[k];
02253 tmp += m_molalities[k] * z_k * z_k * sigma / 2.0;
02254 }
02255 }
02256 m_dlnActCoeffMolaldT[m_indexSolvent] += coeff * tmp;
02257 break;
02258
02259 case DHFORM_BDOT_ACOMMON:
02260 denomTmp *= m_Aionic[0];
02261 for (int k = 0; k < m_kk; k++) {
02262 z_k = m_speciesCharge[k];
02263 m_dlnActCoeffMolaldT[k] =
02264 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp);
02265 }
02266 if (denomTmp > 0.0) {
02267 y = denomTmp;
02268 yp1 = y + 1.0;
02269 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02270 } else {
02271 sigma = 0.0;
02272 }
02273 m_dlnActCoeffMolaldT[m_indexSolvent] =
02274 2.0 /3.0 * dAdT * m_Mnaught *
02275 m_IionicMolality * sqrtI * sigma;
02276 break;
02277
02278 case DHFORM_BETAIJ:
02279 denomTmp *= m_Aionic[0];
02280 for (int k = 0; k < m_kk; k++) {
02281 if (k != m_indexSolvent) {
02282 z_k = m_speciesCharge[k];
02283 m_dlnActCoeffMolaldT[k] =
02284 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp);
02285 }
02286 }
02287 if (denomTmp > 0.0) {
02288 y = denomTmp;
02289 yp1 = y + 1.0;
02290 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02291 } else {
02292 sigma = 0.0;
02293 }
02294 m_dlnActCoeffMolaldT[m_indexSolvent] =
02295 2.0 /3.0 * dAdT * m_Mnaught *
02296 m_IionicMolality * sqrtI * sigma;
02297 break;
02298
02299 case DHFORM_PITZER_BETAIJ:
02300 denomTmp *= m_Aionic[0];
02301 tmpLn = log(1.0 + denomTmp);
02302 for (int k = 0; k < m_kk; k++) {
02303 if (k != m_indexSolvent) {
02304 z_k = m_speciesCharge[k];
02305 m_dlnActCoeffMolaldT[k] =
02306 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp)
02307 - 2.0 * z_k * z_k * dAdT * tmpLn
02308 / (m_B_Debye * m_Aionic[0]);
02309 m_dlnActCoeffMolaldT[k] /= 3.0;
02310 }
02311 }
02312
02313 sigma = 1.0 / ( 1.0 + denomTmp);
02314 m_dlnActCoeffMolaldT[m_indexSolvent] =
02315 2.0 /3.0 * dAdT * m_Mnaught *
02316 m_IionicMolality * sqrtI * sigma;
02317 break;
02318
02319 default:
02320 printf("ERROR\n");
02321 exit(EXIT_FAILURE);
02322 break;
02323 }
02324
02325
02326 }
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341 void DebyeHuckel::s_update_d2lnMolalityActCoeff_dT2() const {
02342 double z_k, coeff, tmp, y, yp1, sigma, tmpLn;
02343 int k;
02344 double dAdT = dA_DebyedT_TP();
02345 double d2AdT2 = d2A_DebyedT2_TP();
02346 if (d2AdT2 == 0.0 && dAdT == 0.0) {
02347 for (k = 0; k < m_kk; k++) {
02348 m_d2lnActCoeffMolaldT2[k] = 0.0;
02349 }
02350 return;
02351 }
02352
02353
02354
02355
02356
02357 double xmolSolvent = moleFraction(m_indexSolvent);
02358 xmolSolvent = MAX(8.689E-3, xmolSolvent);
02359
02360
02361 double sqrtI = sqrt(m_IionicMolality);
02362 double numd2AdT2Tmp = d2AdT2 * sqrtI;
02363 double denomTmp = m_B_Debye * sqrtI;
02364
02365 switch (m_formDH) {
02366 case DHFORM_DILUTE_LIMIT:
02367 for (int k = 0; k < m_kk; k++) {
02368 m_d2lnActCoeffMolaldT2[k] =
02369 m_lnActCoeffMolal[k] * d2AdT2 / m_A_Debye;
02370 }
02371 break;
02372
02373 case DHFORM_BDOT_AK:
02374 for (int k = 0; k < m_kk; k++) {
02375 z_k = m_speciesCharge[k];
02376 m_d2lnActCoeffMolaldT2[k] =
02377 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp * m_Aionic[k]);
02378 }
02379
02380 m_d2lnActCoeffMolaldT2[m_indexSolvent] = 0.0;
02381
02382 coeff = 2.0 / 3.0 * d2AdT2 * m_Mnaught * sqrtI;
02383 tmp = 0.0;
02384 if (denomTmp > 0.0) {
02385 for (int k = 0; k < m_kk; k++) {
02386 y = denomTmp * m_Aionic[k];
02387 yp1 = y + 1.0;
02388 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02389 z_k = m_speciesCharge[k];
02390 tmp += m_molalities[k] * z_k * z_k * sigma / 2.0;
02391 }
02392 }
02393 m_d2lnActCoeffMolaldT2[m_indexSolvent] += coeff * tmp;
02394 break;
02395
02396 case DHFORM_BDOT_ACOMMON:
02397 denomTmp *= m_Aionic[0];
02398 for (int k = 0; k < m_kk; k++) {
02399 z_k = m_speciesCharge[k];
02400 m_d2lnActCoeffMolaldT2[k] =
02401 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp);
02402 }
02403 if (denomTmp > 0.0) {
02404 y = denomTmp;
02405 yp1 = y + 1.0;
02406 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02407 } else {
02408 sigma = 0.0;
02409 }
02410 m_d2lnActCoeffMolaldT2[m_indexSolvent] =
02411 2.0 /3.0 * d2AdT2 * m_Mnaught *
02412 m_IionicMolality * sqrtI * sigma;
02413 break;
02414
02415 case DHFORM_BETAIJ:
02416 denomTmp *= m_Aionic[0];
02417 for (int k = 0; k < m_kk; k++) {
02418 if (k != m_indexSolvent) {
02419 z_k = m_speciesCharge[k];
02420 m_d2lnActCoeffMolaldT2[k] =
02421 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp);
02422 }
02423 }
02424 if (denomTmp > 0.0) {
02425 y = denomTmp;
02426 yp1 = y + 1.0;
02427 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 -2.0*log(yp1));
02428 } else {
02429 sigma = 0.0;
02430 }
02431 m_d2lnActCoeffMolaldT2[m_indexSolvent] =
02432 2.0 /3.0 * d2AdT2 * m_Mnaught *
02433 m_IionicMolality * sqrtI * sigma;
02434 break;
02435
02436 case DHFORM_PITZER_BETAIJ:
02437 denomTmp *= m_Aionic[0];
02438 tmpLn = log(1.0 + denomTmp);
02439 for (int k = 0; k < m_kk; k++) {
02440 if (k != m_indexSolvent) {
02441 z_k = m_speciesCharge[k];
02442 m_d2lnActCoeffMolaldT2[k] =
02443 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp)
02444 - 2.0 * z_k * z_k * d2AdT2 * tmpLn
02445 / (m_B_Debye * m_Aionic[0]);
02446 m_d2lnActCoeffMolaldT2[k] /= 3.0;
02447 }
02448 }
02449
02450 sigma = 1.0 / ( 1.0 + denomTmp);
02451 m_d2lnActCoeffMolaldT2[m_indexSolvent] =
02452 2.0 /3.0 * d2AdT2 * m_Mnaught *
02453 m_IionicMolality * sqrtI * sigma;
02454 break;
02455
02456 default:
02457 printf("ERROR\n");
02458 exit(EXIT_FAILURE);
02459 break;
02460 }
02461 }
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476 void DebyeHuckel::s_update_dlnMolalityActCoeff_dP() const {
02477 double z_k, coeff, tmp, y, yp1, sigma, tmpLn;
02478 int k, est;
02479 double dAdP = dA_DebyedP_TP();
02480 if (dAdP == 0.0) {
02481 for (k = 0; k < m_kk; k++) {
02482 m_dlnActCoeffMolaldP[k] = 0.0;
02483 }
02484 return;
02485 }
02486
02487
02488
02489
02490 double xmolSolvent = moleFraction(m_indexSolvent);
02491 xmolSolvent = MAX(8.689E-3, xmolSolvent);
02492
02493
02494 double sqrtI = sqrt(m_IionicMolality);
02495 double numdAdPTmp = dAdP * sqrtI;
02496 double denomTmp = m_B_Debye * sqrtI;
02497
02498 switch (m_formDH) {
02499 case DHFORM_DILUTE_LIMIT:
02500 for (int k = 0; k < m_kk; k++) {
02501 m_dlnActCoeffMolaldP[k] =
02502 m_lnActCoeffMolal[k] * dAdP / m_A_Debye;
02503 }
02504 break;
02505
02506 case DHFORM_BDOT_AK:
02507 for (int k = 0; k < m_kk; k++) {
02508 est = m_electrolyteSpeciesType[k];
02509 if (est == cEST_nonpolarNeutral) {
02510 m_lnActCoeffMolal[k] = 0.0;
02511 } else {
02512 z_k = m_speciesCharge[k];
02513 m_dlnActCoeffMolaldP[k] =
02514 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp * m_Aionic[k]);
02515 }
02516 }
02517
02518 m_dlnActCoeffMolaldP[m_indexSolvent] = 0.0;
02519
02520 coeff = 2.0 / 3.0 * dAdP * m_Mnaught * sqrtI;
02521 tmp = 0.0;
02522 if (denomTmp > 0.0) {
02523 for (int k = 0; k < m_kk; k++) {
02524 y = denomTmp * m_Aionic[k];
02525 yp1 = y + 1.0;
02526 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02527 z_k = m_speciesCharge[k];
02528 tmp += m_molalities[k] * z_k * z_k * sigma / 2.0;
02529 }
02530 }
02531 m_dlnActCoeffMolaldP[m_indexSolvent] += coeff * tmp;
02532 break;
02533
02534 case DHFORM_BDOT_ACOMMON:
02535 denomTmp *= m_Aionic[0];
02536 for (int k = 0; k < m_kk; k++) {
02537 z_k = m_speciesCharge[k];
02538 m_dlnActCoeffMolaldP[k] =
02539 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp);
02540 }
02541 if (denomTmp > 0.0) {
02542 y = denomTmp;
02543 yp1 = y + 1.0;
02544 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02545 } else {
02546 sigma = 0.0;
02547 }
02548 m_dlnActCoeffMolaldP[m_indexSolvent] =
02549 2.0 /3.0 * dAdP * m_Mnaught *
02550 m_IionicMolality * sqrtI * sigma;
02551 break;
02552
02553 case DHFORM_BETAIJ:
02554 denomTmp *= m_Aionic[0];
02555 for (int k = 0; k < m_kk; k++) {
02556 if (k != m_indexSolvent) {
02557 z_k = m_speciesCharge[k];
02558 m_dlnActCoeffMolaldP[k] =
02559 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp);
02560 }
02561 }
02562 if (denomTmp > 0.0) {
02563 y = denomTmp;
02564 yp1 = y + 1.0;
02565 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
02566 } else {
02567 sigma = 0.0;
02568 }
02569 m_dlnActCoeffMolaldP[m_indexSolvent] =
02570 2.0 /3.0 * dAdP * m_Mnaught *
02571 m_IionicMolality * sqrtI * sigma;
02572 break;
02573
02574 case DHFORM_PITZER_BETAIJ:
02575 denomTmp *= m_Aionic[0];
02576 tmpLn = log(1.0 + denomTmp);
02577 for (int k = 0; k < m_kk; k++) {
02578 if (k != m_indexSolvent) {
02579 z_k = m_speciesCharge[k];
02580 m_dlnActCoeffMolaldP[k] =
02581 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp)
02582 - 2.0 * z_k * z_k * dAdP * tmpLn
02583 / (m_B_Debye * m_Aionic[0]);
02584 m_dlnActCoeffMolaldP[k] /= 3.0;
02585 }
02586 }
02587
02588 sigma = 1.0 / ( 1.0 + denomTmp);
02589 m_dlnActCoeffMolaldP[m_indexSolvent] =
02590 2.0 /3.0 * dAdP * m_Mnaught *
02591 m_IionicMolality * sqrtI * sigma;
02592 break;
02593
02594 default:
02595 printf("ERROR\n");
02596 exit(EXIT_FAILURE);
02597 break;
02598 }
02599 }
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622 }