// In this routine we must be sure to only find the water branch of the // curve and not the gas branch void PDSS_Water::setPressure(doublereal p) { doublereal T = m_temp; doublereal dens = m_dens; int waterState = WATER_LIQUID; if (T > m_sub->Tcrit()) { waterState = WATER_SUPERCRIT; } #ifdef DEBUG_HKM //printf("waterPDSS: set pres = %g t = %g, waterState = %d\n", // p, T, waterState); #endif doublereal dd = m_sub->density(T, p, waterState, dens); if (dd <= 0.0) { std::string stateString = "T = " + fp2str(T) + " K and p = " + fp2str(p) + " Pa"; throw CanteraError("PDSS_Water:setPressure()", "Failed to set water SS state: " + stateString); } m_dens = dd; m_pres = p; // We are only putting the phase check here because of speed considerations. m_iState = m_sub->phaseState(true); if (! m_allowGasPhase) { if (m_iState != WATER_SUPERCRIT && m_iState != WATER_LIQUID && m_iState != WATER_UNSTABLELIQUID) { throw CanteraError("PDSS_Water::setPressure", "Water State isn't liquid or crit"); } } }
void WaterPropsIAPWS::corr1(doublereal temperature, doublereal pressure, doublereal& densLiq, doublereal& densGas, doublereal& pcorr) { densLiq = density(temperature, pressure, WATER_LIQUID, densLiq); if (densLiq <= 0.0) { throw CanteraError("WaterPropsIAPWS::corr1", "Error occurred trying to find liquid density at (T,P) = " + fp2str(temperature) + " " + fp2str(pressure)); } setState_TR(temperature, densLiq); doublereal prL = m_phi->phiR(); densGas = density(temperature, pressure, WATER_GAS, densGas); if (densGas <= 0.0) { throw CanteraError("WaterPropsIAPWS::corr1", "Error occurred trying to find gas density at (T,P) = " + fp2str(temperature) + " " + fp2str(pressure)); } setState_TR(temperature, densGas); doublereal prG = m_phi->phiR(); doublereal rhs = (prL - prG) + log(densLiq/densGas); rhs /= (1.0/densGas - 1.0/densLiq); pcorr = rhs * Rgas * temperature / M_water; }
double WaterProps::isothermalCompressibility_IAPWS(double temp, double press) { double dens = m_waterIAPWS->density(temp, press, WATER_LIQUID); if (dens < 0.0) { throw CanteraError("WaterProps::isothermalCompressibility_IAPWS", "Unable to solve for density at T = " + fp2str(temp) + " and P = " + fp2str(press)); } double kappa = m_waterIAPWS->isothermalCompressibility(); return kappa; }
double WaterProps::coeffThermalExp_IAPWS(double temp, double press) { double dens = m_waterIAPWS->density(temp, press, WATER_LIQUID); if (dens < 0.0) { throw CanteraError("WaterProps::coeffThermalExp_IAPWS", "Unable to solve for density at T = " + fp2str(temp) + " and P = " + fp2str(press)); } double cte = m_waterIAPWS->coeffThermExp(); return cte; }
/** * For reactions that transfer charge across a potential difference, * the activation energies are modified by the potential difference. * (see, for example, ...). This method applies this correction. */ void InterfaceKinetics::applyButlerVolmerCorrection(doublereal* kf) { int i; int n, nsp, k, ik=0; doublereal rt = GasConstant*thermo(0).temperature(); doublereal rrt = 1.0/rt; int np = nPhases(); // compute the electrical potential energy of each species for (n = 0; n < np; n++) { nsp = thermo(n).nSpecies(); for (k = 0; k < nsp; k++) { m_pot[ik] = Faraday*thermo(n).charge(k)*m_phi[n]; ik++; } } // Compute the change in electrical potential energy for each // reaction. This will only be non-zero if a potential // difference is present. m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_pot), DATA_PTR(m_rwork)); // Modify the reaction rates. Only modify those with a // non-zero activation energy, and do not decrease the // activation energy below zero. doublereal eamod; #ifdef DEBUG_MODE double ea; #endif int nct = m_beta.size(); int irxn; for (i = 0; i < nct; i++) { irxn = m_ctrxn[i]; eamod = m_beta[i]*m_rwork[irxn]; if (eamod != 0.0 && m_E[irxn] != 0.0) { #ifdef DEBUG_MODE ea = GasConstant * m_E[irxn]; if (eamod + ea < 0.0) { writelog("Warning: act energy mod too large!\n"); writelog(" Delta phi = "+fp2str(m_rwork[irxn]/Faraday)+"\n"); writelog(" Delta Ea = "+fp2str(eamod)+"\n"); writelog(" Ea = "+fp2str(ea)+"\n"); for (n = 0; n < np; n++) { writelog("Phase "+int2str(n)+": phi = " +fp2str(m_phi[n])+"\n"); } } #endif kf[irxn] *= exp(-eamod*rrt); } } }
void vcs_VolPhase::setMoleFractionsState(const double totalMoles, const double* const moleFractions, const int vcsStateStatus) { if (totalMoles != 0.0) { // There are other ways to set the mole fractions when VCS_STATECALC // is set to a normal settting. if (vcsStateStatus != VCS_STATECALC_TMP) { throw CanteraError("vcs_VolPhase::setMolesFractionsState", "inappropriate usage"); } m_UpToDate = false; m_vcsStateStatus = VCS_STATECALC_TMP; if (m_existence == VCS_PHASE_EXIST_ZEROEDPHASE) { throw CanteraError("vcs_VolPhase::setMolesFractionsState", "inappropriate usage"); } m_existence = VCS_PHASE_EXIST_YES; } else { m_UpToDate = true; m_vcsStateStatus = vcsStateStatus; m_existence = std::min(m_existence, VCS_PHASE_EXIST_NO); } double fractotal = 1.0; v_totalMoles = totalMoles; if (m_totalMolesInert > 0.0) { if (m_totalMolesInert > v_totalMoles) { throw CanteraError("vcs_VolPhase::setMolesFractionsState", "inerts greater than total: " + fp2str(v_totalMoles) + " " + fp2str(m_totalMolesInert)); } fractotal = 1.0 - m_totalMolesInert/v_totalMoles; } double sum = 0.0; for (size_t k = 0; k < m_numSpecies; k++) { Xmol_[k] = moleFractions[k]; sum += moleFractions[k]; } if (sum == 0.0) { throw CanteraError("vcs_VolPhase::setMolesFractionsState", "inappropriate usage"); } if (sum != fractotal) { for (size_t k = 0; k < m_numSpecies; k++) { Xmol_[k] *= (fractotal /sum); } } _updateMoleFractionDependencies(); }
/*! * @param c Vector of five doubles: The doubles are the parameters, * a, b, c, d, and e of the SRI parameterization */ virtual void init(const vector_fp& c) { if (c[2] < 0.0) { throw CanteraError("SRI5::init()", "m_c parameter is less than zero: " + fp2str(c[2])); } if (c[3] < 0.0) { throw CanteraError("SRI5::init()", "m_d parameter is less than zero: " + fp2str(c[3])); } m_a = c[0]; m_b = c[1]; m_c = c[2]; m_d = c[3]; m_e = c[4]; }
//================================================================================================= bool SimpleTransport::update_T() { doublereal t = m_thermo->temperature(); if (t == m_temp) { return false; } if (t < 0.0) { throw CanteraError("SimpleTransport::update_T", "negative temperature "+fp2str(t)); } // Compute various functions of temperature m_temp = t; // temperature has changed, so polynomial temperature // interpolations will need to be reevaluated. // Set all of these flags to false m_visc_mix_ok = false; m_visc_temp_ok = false; m_cond_temp_ok = false; m_cond_mix_ok = false; m_diff_mix_ok = false; m_diff_temp_ok = false; return true; }
string PlusConstant1::write(const std::string& arg) const { if (m_c == 0.0) { return m_f1->write(arg); } return m_f1->write(arg) + " + " + fp2str(m_c); }
void addFloatArray(XML_Node& node, const std::string& title, const size_t n, const doublereal* const vals, const std::string& units, const std::string& type, const doublereal minval, const doublereal maxval) { std::string v = ""; for (size_t i = 0; i < n; i++) { v += fp2str(vals[i],FP_Format); if (i == n-1) { v += "\n"; } else if (i > 0 && (i+1) % 3 == 0) { v += ",\n"; } else { v += ", "; } } XML_Node& f = node.addChild("floatArray",v); f.addAttribute("title",title); if (type != "") { f.addAttribute("type",type); } f.addAttribute("size", double(n)); if (units != "") { f.addAttribute("units",units); } if (minval != Undef) { f.addAttribute("min",minval); } if (maxval != Undef) { f.addAttribute("max",maxval); } }
/* * This is called whenever a transport property is * requested. * The first task is to check whether the temperature has changed * since the last call to update_temp(). * If it hasn't then an immediate return is carried out. * * @internal */ void LiquidTransport::update_temp() { // First make a decision about whether we need to recalculate doublereal t = m_thermo->temperature(); if (t == m_temp) return; // Next do a reality check on temperature value if (t < 0.0) { throw CanteraError("LiquidTransport::update_temp()", "negative temperature "+fp2str(t)); } // Compute various direct functions of temperature m_temp = t; m_logt = log(m_temp); m_kbt = Boltzmann * m_temp; // temperature has changed so temp flags are flipped m_visc_temp_ok = false; m_diff_temp_ok = false; // temperature has changed, so polynomial temperature // interpolations will need to be reevaluated. // This means that many concentration m_visc_conc_ok = false; m_cond_temp_ok = false; // Mixture stuff needs to be evaluated m_visc_mix_ok = false; m_diff_mix_ok = false; // m_cond_mix_ok = false; (don't need it because a lower lvl flag is set }
/* * @internal This is called whenever a transport property is * requested from ThermoSubstance if the temperature has changed * since the last call to update_T. */ void MixTransport::update_T() { doublereal t = m_thermo->temperature(); if (t == m_temp) return; if (t < 0.0) { throw CanteraError("MixTransport::update_T", "negative temperature "+fp2str(t)); } m_temp = t; m_logt = log(m_temp); m_kbt = Boltzmann * m_temp; m_sqrt_t = sqrt(m_temp); m_t14 = sqrt(m_sqrt_t); m_t32 = m_temp * m_sqrt_t; m_sqrt_kbt = sqrt(Boltzmann*m_temp); // compute powers of log(T) m_polytempvec[0] = 1.0; m_polytempvec[1] = m_logt; m_polytempvec[2] = m_logt*m_logt; m_polytempvec[3] = m_logt*m_logt*m_logt; m_polytempvec[4] = m_logt*m_logt*m_logt*m_logt; // temperature has changed, so polynomial fits will need to be // redone. m_viscmix_ok = false; m_spvisc_ok = false; m_viscwt_ok = false; m_spcond_ok = false; m_bindiff_ok = false; m_condmix_ok = false; }
void LatticePhase::_updateThermo() const { doublereal tnow = temperature(); if (fabs(molarDensity() - m_molar_density)/m_molar_density > 0.0001) { throw CanteraError("_updateThermo","molar density changed from " +fp2str(m_molar_density)+" to "+fp2str(molarDensity())); } if (m_tlast != tnow) { m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0], &m_s0_R[0]); m_tlast = tnow; for (size_t k = 0; k < m_kk; k++) { m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; } m_tlast = tnow; } }
std::string Exp1::write(const std::string& arg) const { string c = ""; if (m_c != 1.0) { c = fp2str(m_c); } return "\\exp("+c+arg+")"; }
double GibbsExcessVPSSTP::checkMFSum(const doublereal * const x) const { doublereal norm = accumulate(x, x + m_kk, 0.0); if (fabs(norm - 1.0) > 1.0E-9) { throw CanteraError("GibbsExcessVPSSTP::checkMFSum", "(MF sum - 1) exceeded tolerance of 1.0E-9:" + fp2str(norm)); } return norm; }
string Sin1::write(const string& arg) const { string c = ""; if (m_c != 1.0) { c = fp2str(m_c); } return "\\sin(" + c + arg + ")"; }
void SingleSpeciesTP::setState_UV(doublereal u, doublereal v, doublereal tol) { doublereal dt; setDensity(1.0/v); for (int n = 0; n < 50; n++) { dt = (u - intEnergy_mass())/cv_mass(); if (dt > 100.0) dt = 100.0; else if (dt < -100.0) dt = -100.0; setTemperature(temperature() + dt); if (fabs(dt) < tol) { return; } } throw CanteraError("setState_UV", "no convergence. dt = " + fp2str(dt)+"\n" +"u = "+fp2str(u)+" v = "+fp2str(v)+"\n"); }
void vcs_VolPhase::setMolesFromVCSCheck(const int vcsStateStatus, const double* molesSpeciesVCS, const double* const TPhMoles) { setMolesFromVCS(vcsStateStatus, molesSpeciesVCS); /* * Check for consistency with TPhMoles[] */ double Tcheck = TPhMoles[VP_ID_]; if (Tcheck != v_totalMoles) { if (vcs_doubleEqual(Tcheck, v_totalMoles)) { Tcheck = v_totalMoles; } else { throw CanteraError("vcs_VolPhase::setMolesFromVCSCheck", "We have a consistency problem: " + fp2str(Tcheck) + " " + fp2str(v_totalMoles)); } } }
void SingleSpeciesTP::setState_UV(doublereal u, doublereal v, doublereal tol) { doublereal dt; if (v == 0.0) { setDensity(1.0E100); } else { setDensity(1.0/v); } for (int n = 0; n < 50; n++) { dt = clip((u - intEnergy_mass())/cv_mass(), -100.0, 100.0); setTemperature(temperature() + dt); if (fabs(dt) < tol) { return; } } throw CanteraError("setState_UV", "no convergence. dt = " + fp2str(dt)+"\n" +"u = "+fp2str(u)+" v = "+fp2str(v)+"\n"); }
double HFC134a::ldens() { if ((T < Tmn) || (T > Tc)) { throw TPX_Error("HFC134a::ldens", "Temperature out of range. T = " + fp2str(T)); } double x1 = T/Tc; double x2 = 1.0 - x1; return 518.2 + 884.13*pow(x2,1.0/3.0) + 485.84*pow(x2,2.0/3.0) + 193.29*pow(x2,10.0/3.0); }
double hydrogen::Psat() { double x = (1.0 - Tt/T)/(1.0 - Tt/Tc); double result; if ((T < Tmn) || (T > Tc)) { throw TPX_Error("hydrogen::Psat", "Temperature out of range. T = " + fp2str(T)); } result = Fhydro[0]*x + Fhydro[1]*x*x + Fhydro[2]*x*x*x + Fhydro[3]*x*pow(1-x, alpha); return exp(result)*Pt; }
void vcs_VolPhase::setTotalMoles(const double totalMols) { v_totalMoles = totalMols; if (m_totalMolesInert > 0.0) { m_existence = VCS_PHASE_EXIST_ALWAYS; AssertThrowMsg(totalMols >= m_totalMolesInert, "vcs_VolPhase::setTotalMoles", "totalMoles less than inert moles: " + fp2str(totalMols) + " " + fp2str(m_totalMolesInert)); } else { if (m_singleSpecies && (m_phiVarIndex == 0)) { m_existence = VCS_PHASE_EXIST_ALWAYS; } else { if (totalMols > 0.0) { m_existence = VCS_PHASE_EXIST_YES; } else { m_existence = VCS_PHASE_EXIST_NO; } } } }
double HFC134a::Psat() { if ((T < Tmn) || (T > Tc)) { throw TPX_Error("HFC134a::Psat", "Temperature out of range. T = " + fp2str(T)); } double x1 = T/Tc; double x2 = 1.0 - x1; double f = -7.686556*x2 + 2.311791*pow(x2,1.5) - 2.039554*x2*x2 - 3.583758*pow(x2,4); return Pc*exp(f/x1); }
double oxygen::ldens() { double xx=1-T/Tc, sum=0; if ((T < Tmn) || (T > Tc)) { throw TPX_Error("oxygen::ldens", "Temperature out of range. T = " + fp2str(T)); } for (int i=0; i<=5; i++) { sum+=Doxy[i]*pow(xx,double(i)/3.0); } return sum; }
/* * Check the continuity of properties at the midpoint * temperature. */ void NasaThermo::checkContinuity(std::string name, double tmid, const doublereal* clow, doublereal* chigh) { // heat capacity doublereal cplow = poly4(tmid, clow); doublereal cphigh = poly4(tmid, chigh); doublereal delta = cplow - cphigh; if (fabs(delta/(fabs(cplow)+1.0E-4)) > 0.001) { writelog("\n\n**** WARNING ****\nFor species "+name+ ", discontinuity in cp/R detected at Tmid = " +fp2str(tmid)+"\n"); writelog("\tValue computed using low-temperature polynomial: " +fp2str(cplow)+".\n"); writelog("\tValue computed using high-temperature polynomial: " +fp2str(cphigh)+".\n"); } // enthalpy doublereal hrtlow = enthalpy_RT(tmid, clow); doublereal hrthigh = enthalpy_RT(tmid, chigh); delta = hrtlow - hrthigh; if (fabs(delta/(fabs(hrtlow)+cplow*tmid)) > 0.001) { writelog("\n\n**** WARNING ****\nFor species "+name+ ", discontinuity in h/RT detected at Tmid = " +fp2str(tmid)+"\n"); writelog("\tValue computed using low-temperature polynomial: " +fp2str(hrtlow)+".\n"); writelog("\tValue computed using high-temperature polynomial: " +fp2str(hrthigh)+".\n"); } // entropy doublereal srlow = entropy_R(tmid, clow); doublereal srhigh = entropy_R(tmid, chigh); delta = srlow - srhigh; if (fabs(delta/(fabs(srlow)+cplow)) > 0.001) { writelog("\n\n**** WARNING ****\nFor species "+name+ ", discontinuity in s/R detected at Tmid = " +fp2str(tmid)+"\n"); writelog("\tValue computed using low-temperature polynomial: " +fp2str(srlow)+".\n"); writelog("\tValue computed using high-temperature polynomial: " +fp2str(srhigh)+".\n"); } }
void Plog::validate(const ReactionData& rdata) { double T[] = {200.0, 500.0, 1000.0, 2000.0, 5000.0, 10000.0}; for (pressureIter iter = pressures_.begin(); iter->first < 1000; iter++) { update_C(&iter->first); for (size_t i=0; i < 6; i++) { double k = updateRC(log(T[i]), 1.0/T[i]); if (!(k >= 0)) { // k is NaN. Increment the iterator so that the error // message will correctly indicate that the problematic rate // expression is at the higher of the adjacent pressures. throw CanteraError("Plog::validate", "Invalid rate coefficient for reaction #" + int2str(rdata.number) + ":\n" + rdata.equation + "\n" + "at P = " + fp2str(std::exp((++iter)->first)) + ", T = " + fp2str(T[i])); } } } }
double water::ldens() { double sum=0; int i; if ((T < Tmn) || (T >= Tc)) { throw TPX_Error("water::ldens", "Temperature out of range. T = " + fp2str(T)); } for (i=0; i<8; i++) { sum+=D[i]*pow(1.0 - T/Tc, double(i+1)/3.0); } double density = Roc*(1+sum); return density; }
void SingleSpeciesTP::setState_SP(doublereal s, doublereal p, doublereal tol) { doublereal dt; setPressure(p); for (int n = 0; n < 50; n++) { dt = clip((s - entropy_mass())*temperature()/cp_mass(), -100.0, 100.0); setState_TP(temperature() + dt, p); if (fabs(dt) < tol) { return; } } throw CanteraError("setState_SP","no convergence. dt = " + fp2str(dt)); }
double hydrogen::ldens() { if ((T < Tmn) || (T > Tc)) { throw TPX_Error("hydrogen::ldens", "Temperature out of range. T = " + fp2str(T)); } double x=1-T/Tc; double sum; int i; for (i=1, sum=0; i<=6; i++) { sum+=Dhydro[i]*pow(x, 1+double(i-1)/3.0); } return sum+Roc+Dhydro[0]*pow(x,alpha1); }
double water::Psat() { double log, sum=0,P; if ((T < Tmn) || (T > Tc)) { throw TPX_Error("water::Psat", "Temperature out of range. T = " + fp2str(T)); } for (int i=1; i<=8; i++) { sum += F[i-1]*pow(aww*(T-Tp),double(i-1)); // DGG mod } log = (Tc/T-1)*sum; P=exp(log)*Pc; return P; }