/** * @file VPSSMgr_Water_HKFT.cpp * Definition file for a derived class that handles the calculation * of standard state thermo properties for pure water and * a set of species which obey the HKFT standard state * dependence * (see \ref thermoprops and class * \link Cantera::VPSSMgr_Water_HKFT VPSSMgr_Water_HKFT\endlink). */ /* * Copyright (2005) Sandia Corporation. Under the terms of * Contract DE-AC04-94AL85000 with Sandia Corporation, the * U.S. Government retains certain rights in this software. */ #include "cantera/thermo/VPSSMgr_Water_HKFT.h" #include "cantera/thermo/PDSS_Water.h" #include "cantera/thermo/PDSS_HKFT.h" #include "cantera/thermo/VPStandardStateTP.h" #include "cantera/thermo/GeneralSpeciesThermo.h" #include "cantera/base/xml.h" #include "cantera/base/stringUtils.h" using namespace std; namespace Cantera { VPSSMgr_Water_HKFT::VPSSMgr_Water_HKFT(VPStandardStateTP* vp_ptr, SpeciesThermo* spth) : VPSSMgr(vp_ptr, spth), m_waterSS(0), m_tlastRef(-1.0) { m_useTmpRefStateStorage = true; m_useTmpStandardStateStorage = true; } VPSSMgr_Water_HKFT::VPSSMgr_Water_HKFT(const VPSSMgr_Water_HKFT& right) : VPSSMgr(right.m_vptp_ptr, right.m_spthermo), m_waterSS(0), m_tlastRef(-1.0) { m_useTmpRefStateStorage = true; m_useTmpStandardStateStorage = true; *this = right; } VPSSMgr_Water_HKFT& VPSSMgr_Water_HKFT::operator=(const VPSSMgr_Water_HKFT& b) { if (&b == this) { return *this; } VPSSMgr::operator=(b); m_waterSS = dynamic_cast(m_vptp_ptr->providePDSS(0)); m_tlastRef = -1.0; return *this; } VPSSMgr* VPSSMgr_Water_HKFT::duplMyselfAsVPSSMgr() const { return new VPSSMgr_Water_HKFT(*this); } void VPSSMgr_Water_HKFT::getEnthalpy_RT_ref(doublereal* hrt) const { updateRefStateThermo(); copy(m_h0_RT.begin(), m_h0_RT.end(), hrt); } void VPSSMgr_Water_HKFT::getGibbs_RT_ref(doublereal* grt) const { updateRefStateThermo(); copy(m_g0_RT.begin(), m_g0_RT.end(), grt); } void VPSSMgr_Water_HKFT::getGibbs_ref(doublereal* g) const { getGibbs_RT_ref(g); for (size_t k = 0; k < m_kk; k++) { g[k] *= GasConstant * m_tlast; } } void VPSSMgr_Water_HKFT::getEntropy_R_ref(doublereal* sr) const { updateRefStateThermo(); copy(m_s0_R.begin(), m_s0_R.end(), sr); } void VPSSMgr_Water_HKFT::getCp_R_ref(doublereal* cpr) const { updateRefStateThermo(); copy(m_cp0_R.begin(), m_cp0_R.end(), cpr); } void VPSSMgr_Water_HKFT::getStandardVolumes_ref(doublereal* vol) const { updateRefStateThermo(); copy(m_V0.begin(), m_V0.end(), vol); } void VPSSMgr_Water_HKFT::setState_P(doublereal pres) { if (m_plast != pres) { m_plast = pres; _updateStandardStateThermo(); } } void VPSSMgr_Water_HKFT::setState_T(doublereal temp) { if (m_tlast != temp) { m_tlast = temp; _updateStandardStateThermo(); } } void VPSSMgr_Water_HKFT::setState_TP(doublereal temp, doublereal pres) { if (m_tlast != temp) { m_tlast = temp; m_plast = pres; _updateStandardStateThermo(); } else if (m_plast != pres) { m_plast = pres; _updateStandardStateThermo(); } } void VPSSMgr_Water_HKFT::updateRefStateThermo() const { if (m_tlastRef != m_tlast) { m_tlastRef = m_tlast; _updateRefStateThermo(); } } void VPSSMgr_Water_HKFT::_updateRefStateThermo() const { m_p0 = m_waterSS->pref_safe(m_tlast); m_waterSS->setState_TP(m_tlast, m_p0); m_h0_RT[0] = (m_waterSS->enthalpy_mole()) / (GasConstant * m_tlast); m_s0_R[0] = (m_waterSS->entropy_mole()) / GasConstant; m_cp0_R[0] = (m_waterSS->cp_mole()) / GasConstant; m_g0_RT[0] = (m_hss_RT[0] - m_sss_R[0]); m_V0[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); PDSS* ps; for (size_t k = 1; k < m_kk; k++) { ps = m_vptp_ptr->providePDSS(k); ps->setState_TP(m_tlast, m_p0); m_cp0_R[k] = ps->cp_R(); m_s0_R[k] = ps->entropy_mole() / GasConstant; m_g0_RT[k] = ps->gibbs_RT(); m_h0_RT[k] = m_g0_RT[k] + m_s0_R[k]; #ifdef DEBUG_MODE_NOT double h = ps->enthalpy_RT(); if (fabs(m_h0_RT[k] - h) > 1.0E-4) { printf(" VPSSMgr_Water_HKFT::_updateRefStateThermo:: we have a discrepancy\n"); } #endif m_V0[k] = ps->molarVolume(); } m_waterSS->setState_TP(m_tlast, m_plast); for (size_t k = 1; k < m_kk; k++) { ps = m_vptp_ptr->providePDSS(k); ps->setState_TP(m_tlast, m_plast); } } void VPSSMgr_Water_HKFT::_updateStandardStateThermo() { // Do the water m_waterSS->setState_TP(m_tlast, m_plast); m_hss_RT[0] = (m_waterSS->enthalpy_mole()) / (GasConstant * m_tlast); m_sss_R[0] = (m_waterSS->entropy_mole()) / GasConstant; m_cpss_R[0] = (m_waterSS->cp_mole()) / GasConstant; m_gss_RT[0] = (m_hss_RT[0] - m_sss_R[0]); m_Vss[0] = (m_vptp_ptr->molecularWeight(0)) / (m_waterSS->density()); for (size_t k = 1; k < m_kk; k++) { PDSS* ps = m_vptp_ptr->providePDSS(k); ps->setState_TP(m_tlast, m_plast); m_cpss_R[k] = ps->cp_R(); m_sss_R[k] = ps->entropy_R(); m_gss_RT[k] = ps->gibbs_RT(); m_hss_RT[k] = m_gss_RT[k] + m_sss_R[k]; m_Vss[k] = ps->molarVolume(); } } void VPSSMgr_Water_HKFT::initThermo() { VPSSMgr::initThermo(); } void VPSSMgr_Water_HKFT::initThermoXML(XML_Node& phaseNode, const std::string& id) { VPSSMgr::initThermoXML(phaseNode, id); XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root()); m_waterSS->setState_TP(300., OneAtm); m_Vss[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); for (size_t k = 1; k < m_kk; k++) { string name = m_vptp_ptr->speciesName(k); const XML_Node* s = speciesDB->findByAttr("name", name); if (!s) { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "No species Node for species " + name); } const XML_Node* ss = s->findByName("standardState"); if (!ss) { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "No standardState Node for species " + name); } std::string model = lowercase(ss->attrib("model")); if (model != "hkft") { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "Standard state model for a solute species isn't " "the HKFT standard state model: " + name); } } } PDSS* VPSSMgr_Water_HKFT::createInstallPDSS(size_t k, const XML_Node& speciesNode, const XML_Node* const phaseNode_ptr) { PDSS* kPDSS = 0; const XML_Node* ss = speciesNode.findByName("standardState"); if (!ss) { throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", "No standardState Node for species " + speciesNode["name"]); } // Will have to do something for water // -> make sure it's species 0 // -> make sure it's designated as a real water EOS if (k == 0) { if (speciesNode["name"] != "H2O(L)") { throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", "h2o wrong name: " + speciesNode["name"]); } std::string model = ss->attrib("model"); if (model != "waterIAPWS" && model != "waterPDSS") { throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", "wrong SS mode: " + model); } //VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); delete m_waterSS; m_waterSS = new PDSS_Water(m_vptp_ptr, 0); GeneralSpeciesThermo* genSpthermo = dynamic_cast(m_spthermo); if (!genSpthermo) { throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", "failed dynamic cast"); } genSpthermo->installPDSShandler(k, m_waterSS, this); kPDSS = m_waterSS; } else { if (ss->attrib("model") != "HKFT") { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "standardState model for species isn't " "HKFT: " + speciesNode["name"]); } kPDSS = new PDSS_HKFT(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); GeneralSpeciesThermo* genSpthermo = dynamic_cast(m_spthermo); if (!genSpthermo) { throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", "failed dynamic cast"); } genSpthermo->installPDSShandler(k, kPDSS, this); } return kPDSS; } void VPSSMgr_Water_HKFT::initAllPtrs(VPStandardStateTP* vp_ptr, SpeciesThermo* sp_ptr) { VPSSMgr::initAllPtrs(vp_ptr, sp_ptr); m_waterSS = dynamic_cast(m_vptp_ptr->providePDSS(0)); if (!m_waterSS) { throw CanteraError("VPSSMgr_Water_ConstVol::initAllPtrs", "bad dynamic cast"); } } PDSS_enumType VPSSMgr_Water_HKFT::reportPDSSType(int k) const { return cPDSS_UNDEF; } VPSSMgr_enumType VPSSMgr_Water_HKFT::reportVPSSMgrType() const { return cVPSSMGR_WATER_HKFT; } }