From 19cd590ac2e4a6f1b8c3a105b60b6559e1650c1e Mon Sep 17 00:00:00 2001 From: Harry Moffat Date: Thu, 13 Jul 2006 20:05:11 +0000 Subject: [PATCH] Another iteration on trying to unify the water treatment between the 2 objects. --- Cantera/src/thermo/DebyeHuckel.cpp | 134 +++++++++++++++++++++++---- Cantera/src/thermo/DebyeHuckel.h | 7 ++ Cantera/src/thermo/HMWSoln.cpp | 3 - Cantera/src/thermo/HMWSoln_input.cpp | 65 +++++++++++-- Cantera/src/xml.h | 10 +- 5 files changed, 189 insertions(+), 30 deletions(-) diff --git a/Cantera/src/thermo/DebyeHuckel.cpp b/Cantera/src/thermo/DebyeHuckel.cpp index 556e4e59d..10fce49b7 100644 --- a/Cantera/src/thermo/DebyeHuckel.cpp +++ b/Cantera/src/thermo/DebyeHuckel.cpp @@ -430,6 +430,18 @@ namespace Cantera { } } + /** + * Overwritten setTemperature(double) from State.h. This + * function sets the temperature, and makes sure that + * the value propagates to underlying objects. + */ + void DebyeHuckel::setTemperature(double temp) { + if (m_waterSS) { + m_waterSS->setTemperature(temp); + } + State::setTemperature(temp); + } + // // ------- Activities and Activity Concentrations @@ -890,14 +902,7 @@ namespace Cantera { * species k<\I> at the reference pressure, \f$P_{ref}\f$. */ void DebyeHuckel::getPureGibbs(doublereal* gpure) const { - getGibbs_ref(gpure); - doublereal pref; - doublereal delta_p; - for (int k = 0; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - gpure[k] += delta_p * m_speciesSize[k]; - } + getStandardChemPotentials(gpure); } /** @@ -926,6 +931,10 @@ namespace Cantera { delta_p = m_Pcurrent - pref; hrt[k] += delta_p/ RT * m_speciesSize[k]; } + if (m_waterSS) { + hrt[0] = m_waterSS->enthalpy_mole(); + hrt[0] /= RT; + } } /** @@ -945,6 +954,10 @@ namespace Cantera { void DebyeHuckel:: getEntropy_R(doublereal* sr) const { getEntropy_R_ref(sr); + if (m_waterSS) { + sr[0] = m_waterSS->entropy_mole(); + sr[0] /= GasConstant; + } } /** @@ -963,7 +976,11 @@ namespace Cantera { * constant pressure heat capacity for species k. */ void DebyeHuckel::getCp_R(doublereal* cpr) const { - getCp_R_ref(cpr); + getCp_R_ref(cpr); + if (m_waterSS) { + cpr[0] = m_waterSS->cp_mole(); + cpr[0] /= GasConstant; + } } /** @@ -975,6 +992,10 @@ namespace Cantera { void DebyeHuckel::getStandardVolumes(doublereal *vol) const { copy(m_speciesSize.begin(), m_speciesSize.end(), vol); + if (m_waterSS) { + double dd = m_waterSS->density(); + vol[0] = molecularWeight(0)/dd; + } } @@ -1276,9 +1297,11 @@ namespace Cantera { "Solvent " + solventName + " should be first species"); } - + /* - * Now go get the molar volumes + * Now go get the specification of the standard states for + * species in the solution. This includes the molar volumes + * data blocks for incompressible species. */ XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = @@ -1288,12 +1311,69 @@ namespace Cantera { for (k = 0; k < m_kk; k++) { XML_Node* s = speciesDB->findByAttr("name", sss[k]); + if (!s) { + throw CanteraError("DebyeHuckel::initThermoXML", + "Species Data Base " + sss[k] + " not found"); + } XML_Node *ss = s->findByName("standardState"); - m_speciesSize[k] = getFloat(*ss, "molarVolume", "-"); + if (!ss) { + throw CanteraError("DebyeHuckel::initThermoXML", + "Species " + sss[k] + + " standardState XML block not found"); + } + string modelStringa = ss->attrib("model"); + if (modelStringa == "") { + throw CanteraError("DebyeHuckel::initThermoXML", + "Species " + sss[k] + + " standardState XML block model attribute not found"); + } + string modelString = lowercase(modelStringa); + + if (k == 0) { + if (modelString == "wateriapws" || modelString == "real_water" || + modelString == "waterpdss") { + /* + * Initialize the water standard state model + */ + if (m_waterSS) delete m_waterSS; + m_waterSS = new WaterPDSS(this, 0); + /* + * Fill in the molar volume of water (m3/kmol) + * at standard conditions to fill in the m_speciesSize entry + * with something reasonable. + */ + m_waterSS->setState_TP(300., OneAtm); + double dens = m_waterSS->density(); + double mw = m_waterSS->molecularWeight(); + m_speciesSize[0] = mw / dens; #ifdef DEBUG_HKM_NOT - cout << "species " << sss[k] << " has volume " << - m_speciesSize[k] << endl; + cout << "Solvent species " << sss[k] << " has volume " << + m_speciesSize[k] << endl; #endif + } else if (modelString == "constant_incompressible") { + m_speciesSize[k] = getFloat(*ss, "molarVolume", "-"); +#ifdef DEBUG_HKM_NOT + cout << "species " << sss[k] << " has volume " << + m_speciesSize[k] << endl; +#endif + } else { + throw CanteraError("DebyeHuckel::initThermoXML", + "Solvent SS Model \"" + modelStringa + + "\" is not known"); + } + } else { + if (modelString != "constant_incompressible") { + throw CanteraError("DebyeHuckel::initThermoXML", + "Solute SS Model \"" + modelStringa + + "\" is not known"); + } + m_speciesSize[k] = getFloat(*ss, "molarVolume", "-"); +#ifdef DEBUG_HKM_NOT + cout << "species " << sss[k] << " has volume " << + m_speciesSize[k] << endl; +#endif + } + } /* @@ -1308,10 +1388,32 @@ namespace Cantera { * Look for parameters for A_Debye */ if (acNode.hasChild("A_Debye")) { - m_A_Debye = getFloat(acNode, "A_Debye"); + XML_Node *ss = acNode.findByName("A_Debye"); + string modelStringa = ss->attrib("model"); + string modelString = lowercase(modelStringa); + if (modelString != "") { + if (modelString == "water") { + m_form_A_Debye = A_DEBYE_WATER; + } else { + throw CanteraError("DebyeHuckel::initThermoXML", + "A_Debye Model \"" + modelStringa + + "\" is not known"); + } + } else { + m_A_Debye = getFloat(acNode, "A_Debye"); #ifdef DEBUG_HKM_NOT - cout << "A_Debye = " << m_A_Debye << endl; + cout << "A_Debye = " << m_A_Debye << endl; #endif + } + } + + /* + * Initialize the water property calculator. It will share + * the internal eos water calculator. + */ + if (m_form_A_Debye == A_DEBYE_WATER) { + if (m_waterProps) delete m_waterProps; + m_waterProps = new WaterProps(m_waterSS); } /* diff --git a/Cantera/src/thermo/DebyeHuckel.h b/Cantera/src/thermo/DebyeHuckel.h index d9b3e7901..ba0aa31b0 100644 --- a/Cantera/src/thermo/DebyeHuckel.h +++ b/Cantera/src/thermo/DebyeHuckel.h @@ -272,6 +272,13 @@ namespace Cantera { */ virtual void setMolarDensity(doublereal conc); + /** + * Overwritten setTemperature(double) from State.h. This + * function sets the temperature, and makes sure that + * the value propagates to underlying objects. + */ + virtual void setTemperature(doublereal temp); + /** * The isothermal compressibility. Units: 1/Pa. * The isothermal compressibility is defined as diff --git a/Cantera/src/thermo/HMWSoln.cpp b/Cantera/src/thermo/HMWSoln.cpp index 2662f5853..a0c4ce3c9 100644 --- a/Cantera/src/thermo/HMWSoln.cpp +++ b/Cantera/src/thermo/HMWSoln.cpp @@ -1300,7 +1300,6 @@ namespace Cantera { } return vol; } - /** * A_Debye_TP() (virtual) @@ -1668,8 +1667,6 @@ namespace Cantera { counterIJ_setup(); } - - /** * Calcuate the natural log of the molality-based * activity coefficients. diff --git a/Cantera/src/thermo/HMWSoln_input.cpp b/Cantera/src/thermo/HMWSoln_input.cpp index e57973d76..1c8aea639 100644 --- a/Cantera/src/thermo/HMWSoln_input.cpp +++ b/Cantera/src/thermo/HMWSoln_input.cpp @@ -842,7 +842,9 @@ namespace Cantera { } /* - * Now go get the molar volumes + * Now go get the specification of the standard states for + * species in the solution. This includes the molar volumes + * data blocks for incompressible species. */ XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = @@ -852,20 +854,63 @@ namespace Cantera { for (k = 0; k < m_kk; k++) { XML_Node* s = speciesDB->findByAttr("name", sss[k]); + if (!s) { + throw CanteraError("HMWSoln::initThermoXML", + "Species Data Base " + sss[k] + " not found"); + } XML_Node *ss = s->findByName("standardState"); - m_speciesSize[k] = getFloat(*ss, "molarVolume", "-"); + if (!ss) { + throw CanteraError("HMWSoln::initThermoXML", + "Species " + sss[k] + + " standardState XML block not found"); + } + string modelStringa = ss->attrib("model"); + if (modelStringa == "") { + throw CanteraError("HMWSoln::initThermoXML", + "Species " + sss[k] + + " standardState XML block model attribute not found"); + } + string modelString = lowercase(modelStringa); + if (k == 0) { + if (modelString == "wateriapws" || modelString == "real_water" || + modelString == "waterpdss") { + /* + * Initialize the water standard state model + */ + if (m_waterSS) delete m_waterSS; + m_waterSS = new WaterPDSS(this, 0); + /* + * Fill in the molar volume of water (m3/kmol) + * at standard conditions to fill in the m_speciesSize entry + * with something reasonable. + */ + m_waterSS->setState_TP(300., OneAtm); + double dens = m_waterSS->density(); + double mw = m_waterSS->molecularWeight(); + m_speciesSize[0] = mw / dens; #ifdef DEBUG_HKM_NOT - cout << "species " << sss[k] << " has volume " << - m_speciesSize[k] << endl; + cout << "Solvent species " << sss[k] << " has volume " << + m_speciesSize[k] << endl; #endif + } else { + throw CanteraError("HMWSoln::initThermoXML", + "Solvent SS Model \"" + modelStringa + + "\" is not allowed"); + } + } else { + if (modelString != "constant_incompressible") { + throw CanteraError("HMWSoln::initThermoXML", + "Solute SS Model \"" + modelStringa + + "\" is not known"); + } + m_speciesSize[k] = getFloat(*ss, "molarVolume", "-"); +#ifdef DEBUG_HKM_NOT + cout << "species " << sss[k] << " has volume " << + m_speciesSize[k] << endl; +#endif + } } - /* - * Initialize the water standard state model - */ - if (m_waterSS) delete m_waterSS; - m_waterSS = new WaterPDSS(this, 0); - /* * Initialize the water property calculator. It will share * the internal eos water calculator. diff --git a/Cantera/src/xml.h b/Cantera/src/xml.h index 54dc1cdef..952e083d7 100755 --- a/Cantera/src/xml.h +++ b/Cantera/src/xml.h @@ -100,10 +100,18 @@ namespace Cantera { return attrib(attr); } + /** + * This function searches the attibutes vector for the parameter + * string attribute. If a match is found, the attribute value + * is returned as a string. If no match is found, the empty string + * is returned. + * + * @param(attr) String containing the attribute to be searched for. + */ string attrib(string attr) const { map::const_iterator i = m_attribs.find(attr); if (i != m_attribs.end()) return i->second; - else return ""; + return ""; } map& attribs() { return m_attribs; }