TEST_F(RedlichKister_Test, activityCoeffs) { const std::string valid_file("../data/RedlichKisterVPSSTP_valid.xml"); initializeTestPhaseWithXML(valid_file); test_phase->setState_TP(298., 1.); // Test that mu0 + RT log(activityCoeff * MoleFrac) == mu const double RT = GasConstant * 298.; vector_fp mu0(2); vector_fp activityCoeffs(2); vector_fp chemPotentials(2); double xmin = 0.6; double xmax = 0.9; int numSteps = 9; double dx = (xmax-xmin)/(numSteps-1); for(int i=0; i < numSteps; ++i) { const double r = xmin + i*dx; set_r(r); test_phase->getChemPotentials(&chemPotentials[0]); test_phase->getActivityCoefficients(&activityCoeffs[0]); test_phase->getStandardChemPotentials(&mu0[0]); EXPECT_NEAR(chemPotentials[0], mu0[0] + RT*std::log(activityCoeffs[0] * r), 1.e-6); EXPECT_NEAR(chemPotentials[1], mu0[1] + RT*std::log(activityCoeffs[1] * (1-r)), 1.e-6); } }
TEST(HMWSoln, fromScratch) { // Regression test based on HMW_test_3 HMWSoln p; auto sH2O = make_species("H2O(l)", "H:2, O:1", h2oliq_nasa_coeffs); auto sCl = make_species("Cl-", "Cl:1, E:1", 0.0, 298.15, -52.8716, 333.15, -52.8716, 1e5); sCl->charge = -1; auto sH = make_species("H+", "H:1, E:-1", 0.0, 298.15, 0.0, 333.15, 0.0, 1e5); sH->charge = 1; auto sNa = make_species("Na+", "Na:1, E:-1", 0.0, 298.15, -125.5213, 333.15, -125.5213, 1e5); sNa->charge = 1; auto sOH = make_species("OH-", "O:1, H:1, E:1", 0.0, 298.15, -91.523, 333.15, -91.523, 1e5); sOH->charge = -1; for (auto& s : {sH2O, sCl, sH, sNa, sOH}) { p.addSpecies(s); } std::unique_ptr<PDSS_Water> ss(new PDSS_Water()); p.installPDSS(0, std::move(ss)); size_t k = 1; for (double v : {1.3, 1.3, 1.3, 1.3}) { std::unique_ptr<PDSS_ConstVol> ss(new PDSS_ConstVol()); ss->setMolarVolume(v); p.installPDSS(k++, std::move(ss)); } p.setPitzerTempModel("complex"); p.setA_Debye(1.175930); p.initThermo(); set_hmw_interactions(p); p.setMolalitiesByName("Na+:6.0997 Cl-:6.0996986044628 H+:2.1628E-9 OH-:1.3977E-6"); p.setState_TP(150 + 273.15, 101325); size_t N = p.nSpecies(); vector_fp acMol(N), mf(N), activities(N), moll(N), mu0(N); p.getMolalityActivityCoefficients(acMol.data()); p.getMoleFractions(mf.data()); p.getActivities(activities.data()); p.getMolalities(moll.data()); p.getStandardChemPotentials(mu0.data()); double acMolRef[] = {0.9341, 1.0191, 3.9637, 1.0191, 0.4660}; double mfRef[] = {0.8198, 0.0901, 0.0000, 0.0901, 0.0000}; double activitiesRef[] = {0.7658, 6.2164, 0.0000, 6.2164, 0.0000}; double mollRef[] = {55.5084, 6.0997, 0.0000, 6.0997, 0.0000}; double mu0Ref[] = {-317.175788, -186.014558, 0.0017225, -441.615429, -322.000412}; // kJ/gmol for (size_t k = 0 ; k < N; k++) { EXPECT_NEAR(acMol[k], acMolRef[k], 2e-4); EXPECT_NEAR(mf[k], mfRef[k], 2e-4); EXPECT_NEAR(activities[k], activitiesRef[k], 2e-4); EXPECT_NEAR(moll[k], mollRef[k], 2e-4); EXPECT_NEAR(mu0[k]/1e6, mu0Ref[k], 2e-6); } }
/** * @test Test cosine of incidence angle (μ<SUB>0</SUB>) * calculations in MaRC::OblateSpheroid. */ bool test_mu0() { auto const o = std::make_unique<MaRC::OblateSpheroid>(prograde, a, c); constexpr double sub_solar_lat = -65 * C::degree; constexpr double sub_solar_lon = 135 * C::degree; constexpr double lat = 47 * C::degree; constexpr double lon = 330 * C::degree; // Cosine of the incidence angle. double const mu0 = o->mu0(sub_solar_lat, sub_solar_lon, lat, lon); // We assume the Sun is an infinite distance away from the body. // Unit vector from the Sun to the center of the oblate spheroid // (e.g. planet) in body coordindates. MaRC::DVector const rs = { cos(sub_solar_lat) * cos(sub_solar_lon), cos(sub_solar_lat) * sin(sub_solar_lon), sin(sub_solar_lat) }; double const radius = o->centric_radius(lat); // Vector from the center of the oblate spheroid to the point on // the surface at the given latitude and longitude. MaRC::DVector const re = { radius * cos(lat) * cos(lon), radius * cos(lat) * sin(lon), radius * sin(lat) }; double const a2 = a * a; double const c2 = c * c; // Normal vector at (lat, lon) (i.e. grad(f(x, y, z))). MaRC::DVector const rn = { 2 * re[0] / a2, 2 * re[1] / a2, 2 * re[2] / c2 }; // Cosine of angle between the Sun and the vector normal to the // surface at (lat, lon), the incidence angle in this case. double const mu0_2 = cos_included_angle(rs, rn); return MaRC::almost_equal(mu0, mu0_2, ulps); }
/// \brief Quantities constructor /// /// Requires properties: /// - everything required by euler::quantities /// - free-stream Reynoldsh number /// - stagnation Prandtl number /// - Sutherland's constant explicit Quantities(io::Properties properties) noexcept : euler::Quantities(properties) , ReInfty_(io::read<quantity::Dimensionless>(properties, "ReInfty")) , Pr0_(io::read<quantity::Dimensionless>(properties, "Pr0")) , S0_(io::read<quantity::Temperature>(properties, "Sutherland0")) , sOverTref_(S0_ / T0_) , sOverTrefP1_(sOverTref_ + 1.0) , Re0_(Re_infinity() * mu_infinity() / (rho_infinity() * u_infinity())) { std::cerr << "Free-stream variables: " << "ReInfty = " << ReInfty_ << " " << "muInfty = " << mu_infinity() << "\n"; std::cerr << "Stagnation variables: " << "Pr0 = " << Pr0_ << " " << "S0 = " << S0_ << " " << "Re0 = " << Re0_ << " " << "mu0 = " << mu0() << "\n"; }
void VCS_PROB::reportCSV(const std::string& reportFile) { size_t k; size_t istart; double vol = 0.0; string sName; FILE* FP = fopen(reportFile.c_str(), "w"); if (!FP) { plogf("Failure to open file\n"); exit(EXIT_FAILURE); } double Temp = T; std::vector<double> volPM(nspecies, 0.0); std::vector<double> activity(nspecies, 0.0); std::vector<double> ac(nspecies, 0.0); std::vector<double> mu(nspecies, 0.0); std::vector<double> mu0(nspecies, 0.0); std::vector<double> molalities(nspecies, 0.0); vol = 0.0; size_t iK = 0; for (size_t iphase = 0; iphase < NPhase; iphase++) { istart = iK; vcs_VolPhase* volP = VPhaseList[iphase]; //const Cantera::ThermoPhase *tptr = volP->ptrThermoPhase(); size_t nSpeciesPhase = volP->nSpecies(); volPM.resize(nSpeciesPhase, 0.0); volP->sendToVCS_VolPM(VCS_DATA_PTR(volPM)); double TMolesPhase = volP->totalMoles(); double VolPhaseVolumes = 0.0; for (k = 0; k < nSpeciesPhase; k++) { iK++; VolPhaseVolumes += volPM[istart + k] * mf[istart + k]; } VolPhaseVolumes *= TMolesPhase; vol += VolPhaseVolumes; } fprintf(FP,"--------------------- VCS_MULTIPHASE_EQUIL FINAL REPORT" " -----------------------------\n"); fprintf(FP,"Temperature = %11.5g kelvin\n", Temp); fprintf(FP,"Pressure = %11.5g Pascal\n", PresPA); fprintf(FP,"Total Volume = %11.5g m**3\n", vol); fprintf(FP,"Number Basis optimizations = %d\n", m_NumBasisOptimizations); fprintf(FP,"Number VCS iterations = %d\n", m_Iterations); iK = 0; for (size_t iphase = 0; iphase < NPhase; iphase++) { istart = iK; vcs_VolPhase* volP = VPhaseList[iphase]; const Cantera::ThermoPhase<doublereal>* tp = volP->ptrThermoPhase(); string phaseName = volP->PhaseName; size_t nSpeciesPhase = volP->nSpecies(); volP->sendToVCS_VolPM(VCS_DATA_PTR(volPM)); double TMolesPhase = volP->totalMoles(); //AssertTrace(TMolesPhase == m_mix->phaseMoles(iphase)); activity.resize(nSpeciesPhase, 0.0); ac.resize(nSpeciesPhase, 0.0); mu0.resize(nSpeciesPhase, 0.0); mu.resize(nSpeciesPhase, 0.0); volPM.resize(nSpeciesPhase, 0.0); molalities.resize(nSpeciesPhase, 0.0); int actConvention = tp->activityConvention(); tp->getActivities(VCS_DATA_PTR(activity)); tp->getActivityCoefficients(VCS_DATA_PTR(ac)); tp->getStandardChemPotentials(VCS_DATA_PTR(mu0)); tp->getPartialMolarVolumes(VCS_DATA_PTR(volPM)); tp->getChemPotentials(VCS_DATA_PTR(mu)); double VolPhaseVolumes = 0.0; for (k = 0; k < nSpeciesPhase; k++) { VolPhaseVolumes += volPM[k] * mf[istart + k]; } VolPhaseVolumes *= TMolesPhase; vol += VolPhaseVolumes; if (actConvention == 1) { const Cantera::MolalityVPSSTP* mTP = static_cast<const Cantera::MolalityVPSSTP*>(tp); tp->getChemPotentials(VCS_DATA_PTR(mu)); mTP->getMolalities(VCS_DATA_PTR(molalities)); tp->getChemPotentials(VCS_DATA_PTR(mu)); if (iphase == 0) { fprintf(FP," Name, Phase, PhaseMoles, Mole_Fract, " "Molalities, ActCoeff, Activity," "ChemPot_SS0, ChemPot, mole_num, PMVol, Phase_Volume\n"); fprintf(FP," , , (kmol), , " " , , ," " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n"); } for (k = 0; k < nSpeciesPhase; k++) { sName = tp->speciesName(k); fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e," "%11.3e, %11.3e, %11.3e, %11.3e, %11.3e\n", sName.c_str(), phaseName.c_str(), TMolesPhase, mf[istart + k], molalities[k], ac[k], activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6, mf[istart + k] * TMolesPhase, volPM[k], VolPhaseVolumes); } } else { if (iphase == 0) { fprintf(FP," Name, Phase, PhaseMoles, Mole_Fract, " "Molalities, ActCoeff, Activity," " ChemPotSS0, ChemPot, mole_num, PMVol, Phase_Volume\n"); fprintf(FP," , , (kmol), , " " , , ," " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n"); } for (k = 0; k < nSpeciesPhase; k++) { molalities[k] = 0.0; } for (k = 0; k < nSpeciesPhase; k++) { sName = tp->speciesName(k); fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e, " "%11.3e, %11.3e,% 11.3e, %11.3e, %11.3e\n", sName.c_str(), phaseName.c_str(), TMolesPhase, mf[istart + k], molalities[k], ac[k], activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6, mf[istart + k] * TMolesPhase, volPM[k], VolPhaseVolumes); } } #ifdef DEBUG_MODE /* * Check consistency: These should be equal */ tp->getChemPotentials(VCS_DATA_PTR(m_gibbsSpecies)+istart); for (k = 0; k < nSpeciesPhase; k++) { if (!vcs_doubleEqual(m_gibbsSpecies[istart+k], mu[k])) { fprintf(FP,"ERROR: incompatibility!\n"); fclose(FP); plogf("ERROR: incompatibility!\n"); exit(EXIT_FAILURE); } } #endif iK += nSpeciesPhase; } fclose(FP); }
RcppExport SEXP nsem3b(SEXP data, SEXP theta, SEXP Sigma, SEXP modelpar, SEXP control ) { // srand ( time(NULL) ); /* initialize random seed: */ Rcpp::NumericVector Theta(theta); Rcpp::NumericMatrix D(data); unsigned nobs = D.nrow(), k = D.ncol(); mat Data(D.begin(), nobs, k, false); // Avoid copying Rcpp::NumericMatrix V(Sigma); mat S(V.begin(), V.nrow(), V.ncol()); S(0,0) = 1; mat iS = inv(S); double detS = det(S); Rcpp::List Modelpar(modelpar); // Rcpp::IntegerVector _nlatent = Modelpar["nlatent"]; unsigned nlatent = _nlatent[0]; Rcpp::IntegerVector _ny0 = Modelpar["nvar0"]; unsigned ny0 = _ny0[0]; Rcpp::IntegerVector _ny1 = Modelpar["nvar1"]; unsigned ny1 = _ny1[0]; Rcpp::IntegerVector _ny2 = Modelpar["nvar2"]; unsigned ny2 = _ny2[0]; Rcpp::IntegerVector _npred0 = Modelpar["npred0"]; unsigned npred0 = _npred0[0]; Rcpp::IntegerVector _npred1 = Modelpar["npred1"]; unsigned npred1 = _npred1[0]; Rcpp::IntegerVector _npred2 = Modelpar["npred2"]; unsigned npred2 = _npred2[0]; Rcpp::List Control(control); Rcpp::NumericVector _lambda = Control["lambda"]; double lambda = _lambda[0]; Rcpp::NumericVector _niter = Control["niter"]; double niter = _niter[0]; Rcpp::NumericVector _Dtol = Control["Dtol"]; double Dtol = _Dtol[0]; rowvec mu0(ny0), lambda0(ny0); rowvec mu1(ny1), lambda1(ny1); rowvec mu2(ny2), lambda2(ny2); rowvec beta0(npred0); rowvec beta1(npred1); rowvec beta2(npred2); rowvec gamma(2); rowvec gamma2(2); unsigned pos=0; for (unsigned i=0; i<ny0; i++) { mu0(i) = Theta[pos]; pos++; } for (unsigned i=0; i<ny1; i++) { mu1(i) = Theta[pos]; pos++; } for (unsigned i=0; i<ny2; i++) { mu2(i) = Theta[pos]; pos++; } for (unsigned i=0; i<ny0; i++) { lambda0(i) = Theta[pos]; pos++; } lambda1(0) = 1; for (unsigned i=1; i<ny1; i++) { lambda1(i) = Theta[pos]; pos++; } lambda2(0) = 1; for (unsigned i=1; i<ny2; i++) { lambda2(i) = Theta[pos]; pos++; } for (unsigned i=0; i<npred0; i++) { beta0(i) = Theta[pos]; pos++; } for (unsigned i=0; i<npred1; i++) { beta1(i) = Theta[pos]; pos++; } for (unsigned i=0; i<npred2; i++) { beta2(i) = Theta[pos]; pos++; } gamma(0) = Theta[pos]; gamma(1) = Theta[pos+1]; gamma2(0) = Theta[pos+2]; gamma2(1) = Theta[pos+3]; // cerr << "mu0=" << mu0 << endl; // cerr << "mu1=" << mu1 << endl; // cerr << "mu2=" << mu2 << endl; // cerr << "lambda0=" << lambda0 << endl; // cerr << "lambda1=" << lambda1 << endl; // cerr << "lambda2=" << lambda2 << endl; // cerr << "beta0=" << beta0 << endl; // cerr << "beta1=" << beta1 << endl; // cerr << "beta2=" << beta2 << endl; // cerr << "gamma=" << gamma << endl; // cerr << "gamma2=" << gamma2 << endl; mat lap(nobs,4); for (unsigned i=0; i<nobs; i++) { rowvec newlap = laNRb(Data.row(i), iS, detS, mu0, mu1, mu2, lambda0, lambda1, lambda2, beta0,beta1, beta2, gamma, gamma2, Dtol,niter,lambda); lap.row(i) = newlap; } List res; res["indiv"] = lap; res["logLik"] = sum(lap.col(0)) + (3-V.nrow())*log(2.0*datum::pi)*nobs/2; res["norm0"] = (3-V.nrow())*log(2*datum::pi)/2; return res; }
void VCS_PROB::reportCSV(const std::string& reportFile) { FILE* FP = fopen(reportFile.c_str(), "w"); if (!FP) { throw CanteraError("VCS_PROB::reportCSV", "Failure to open file"); } vector_fp volPM(nspecies, 0.0); vector_fp activity(nspecies, 0.0); vector_fp ac(nspecies, 0.0); vector_fp mu(nspecies, 0.0); vector_fp mu0(nspecies, 0.0); vector_fp molalities(nspecies, 0.0); double vol = 0.0; size_t iK = 0; for (size_t iphase = 0; iphase < NPhase; iphase++) { size_t istart = iK; vcs_VolPhase* volP = VPhaseList[iphase]; size_t nSpeciesPhase = volP->nSpecies(); volPM.resize(nSpeciesPhase, 0.0); volP->sendToVCS_VolPM(&volPM[0]); double TMolesPhase = volP->totalMoles(); double VolPhaseVolumes = 0.0; for (size_t k = 0; k < nSpeciesPhase; k++) { iK++; VolPhaseVolumes += volPM[istart + k] * mf[istart + k]; } VolPhaseVolumes *= TMolesPhase; vol += VolPhaseVolumes; } fprintf(FP,"--------------------- VCS_MULTIPHASE_EQUIL FINAL REPORT" " -----------------------------\n"); fprintf(FP,"Temperature = %11.5g kelvin\n", T); fprintf(FP,"Pressure = %11.5g Pascal\n", PresPA); fprintf(FP,"Total Volume = %11.5g m**3\n", vol); fprintf(FP,"Number Basis optimizations = %d\n", m_NumBasisOptimizations); fprintf(FP,"Number VCS iterations = %d\n", m_Iterations); iK = 0; for (size_t iphase = 0; iphase < NPhase; iphase++) { size_t istart = iK; vcs_VolPhase* volP = VPhaseList[iphase]; const ThermoPhase* tp = volP->ptrThermoPhase(); string phaseName = volP->PhaseName; size_t nSpeciesPhase = volP->nSpecies(); volP->sendToVCS_VolPM(&volPM[0]); double TMolesPhase = volP->totalMoles(); activity.resize(nSpeciesPhase, 0.0); ac.resize(nSpeciesPhase, 0.0); mu0.resize(nSpeciesPhase, 0.0); mu.resize(nSpeciesPhase, 0.0); volPM.resize(nSpeciesPhase, 0.0); molalities.resize(nSpeciesPhase, 0.0); int actConvention = tp->activityConvention(); tp->getActivities(&activity[0]); tp->getActivityCoefficients(&ac[0]); tp->getStandardChemPotentials(&mu0[0]); tp->getPartialMolarVolumes(&volPM[0]); tp->getChemPotentials(&mu[0]); double VolPhaseVolumes = 0.0; for (size_t k = 0; k < nSpeciesPhase; k++) { VolPhaseVolumes += volPM[k] * mf[istart + k]; } VolPhaseVolumes *= TMolesPhase; vol += VolPhaseVolumes; if (actConvention == 1) { const MolalityVPSSTP* mTP = static_cast<const MolalityVPSSTP*>(tp); tp->getChemPotentials(&mu[0]); mTP->getMolalities(&molalities[0]); tp->getChemPotentials(&mu[0]); if (iphase == 0) { fprintf(FP," Name, Phase, PhaseMoles, Mole_Fract, " "Molalities, ActCoeff, Activity," "ChemPot_SS0, ChemPot, mole_num, PMVol, Phase_Volume\n"); fprintf(FP," , , (kmol), , " " , , ," " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n"); } for (size_t k = 0; k < nSpeciesPhase; k++) { std::string sName = tp->speciesName(k); fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e," "%11.3e, %11.3e, %11.3e, %11.3e, %11.3e\n", sName.c_str(), phaseName.c_str(), TMolesPhase, mf[istart + k], molalities[k], ac[k], activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6, mf[istart + k] * TMolesPhase, volPM[k], VolPhaseVolumes); } } else { if (iphase == 0) { fprintf(FP," Name, Phase, PhaseMoles, Mole_Fract, " "Molalities, ActCoeff, Activity," " ChemPotSS0, ChemPot, mole_num, PMVol, Phase_Volume\n"); fprintf(FP," , , (kmol), , " " , , ," " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n"); } for (size_t k = 0; k < nSpeciesPhase; k++) { molalities[k] = 0.0; } for (size_t k = 0; k < nSpeciesPhase; k++) { std::string sName = tp->speciesName(k); fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e, " "%11.3e, %11.3e,% 11.3e, %11.3e, %11.3e\n", sName.c_str(), phaseName.c_str(), TMolesPhase, mf[istart + k], molalities[k], ac[k], activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6, mf[istart + k] * TMolesPhase, volPM[k], VolPhaseVolumes); } } iK += nSpeciesPhase; } fclose(FP); }
/// \brief $\mu = \overline{\mu} / \overline{\mu}_0$ inline quantity::Dimensionless mu (const quantity::DynamicViscosity dynamicViscosity) const noexcept { return dynamicViscosity / mu0(); }