ThermoPhase* newPhase(XML_Node& xmlphase) { string model = xmlphase.child("thermo")["model"]; ThermoPhase* t = newThermoPhase(model); if (model == "singing cows") { throw CanteraError("ThermoPhase::newPhase", "Cows don't sing"); } else if (model == "HMW") { HMWSoln* p = dynamic_cast<HMWSoln*>(t); p->constructPhaseXML(xmlphase,""); } else if (model == "IonsFromNeutralMolecule") { IonsFromNeutralVPSSTP* p = dynamic_cast<IonsFromNeutralVPSSTP*>(t); p->constructPhaseXML(xmlphase,""); } else { importPhase(xmlphase, t); } return t; }
/* * Create a new ThermoPhase object and initializes it according to * the XML tree database. This routine first looks up the * identity of the model for the solution thermodynamics in the * model attribute of the thermo child of the xml phase * node. Then, it does a string lookup on the model to figure out * what ThermoPhase derived class is assigned. It creates a new * instance of that class, and then calls importPhase() to * populate that class with the correct parameters from the XML * tree. */ ThermoPhase* newPhase(XML_Node& xmlphase) { const XML_Node& th = xmlphase.child("thermo"); string model = th["model"]; ThermoPhase* t = newThermoPhase(model); if (model == "singing cows") { throw CanteraError(" newPhase", "Cows don't sing"); } #ifdef WITH_ELECTROLYTES else if (model == "HMW") { HMWSoln* p = dynamic_cast<HMWSoln*>(t); p->constructPhaseXML(xmlphase,""); } #endif #ifdef WITH_IDEAL_SOLUTIONS else if (model == "IonsFromNeutralMolecule") { IonsFromNeutralVPSSTP* p = dynamic_cast<IonsFromNeutralVPSSTP*>(t); p->constructPhaseXML(xmlphase,""); } #endif else { importPhase(xmlphase, t); } return t; }
TEST(IonsFromNeutralConstructor, fromScratch) { auto neutral = make_shared<MargulesVPSSTP>(); auto sKCl = make_shomate_species("KCl(L)", "K:1 Cl:1", kcl_shomate_coeffs); neutral->addSpecies(sKCl); std::unique_ptr<PDSS_ConstVol> ssKCl(new PDSS_ConstVol()); ssKCl->setMolarVolume(0.03757); neutral->installPDSS(0, std::move(ssKCl)); neutral->initThermo(); IonsFromNeutralVPSSTP p; p.setNeutralMoleculePhase(neutral); auto sKp = make_shared<Species>("K+", parseCompString("K:1"), 1); auto sClm = make_shared<Species>("Cl-", parseCompString("Cl:1"), -1); sClm->extra["special_species"] = true; p.addSpecies(sKp); p.addSpecies(sClm); std::unique_ptr<PDSS_IonsFromNeutral> ssKp(new PDSS_IonsFromNeutral()); std::unique_ptr<PDSS_IonsFromNeutral> ssClm(new PDSS_IonsFromNeutral()); ssKp->setNeutralSpeciesMultiplier("KCl(L)", 1.2); ssClm->setNeutralSpeciesMultiplier("KCl(L)", 1.5); ssClm->setSpecialSpecies(); p.installPDSS(0, std::move(ssKp)); p.installPDSS(1, std::move(ssClm)); p.initThermo(); ASSERT_EQ((int) p.nSpecies(), 2); p.setState_TPX(500, 2e5, "K+:0.1, Cl-:0.1"); vector_fp mu(p.nSpecies()); p.getChemPotentials(mu.data()); // Values for regression testing only -- same as XML test EXPECT_NEAR(p.density(), 1984.3225978174073, 1e-6); EXPECT_NEAR(p.enthalpy_mass(), -8035317241137.971, 1e-1); EXPECT_NEAR(mu[0], -4.66404010e+08, 1e1); EXPECT_NEAR(mu[1], -2.88157298e+06, 1e-1); }