int vcs_equilibrate_1(MultiPhase& s, int ixy, int estimateEquil, int printLvl, int solver, doublereal tol, int maxsteps, int maxiter, int loglevel) { warn_deprecated("vcs_equilibrate_1", "Use MultiPhase::equilibrate instead. " "To be removed after Cantera 2.2."); static int counter = 0; int retn = 1; int printLvlSub = std::max(0, printLvl-1); s.init(); if (solver == 2) { try { vcs_MultiPhaseEquil* eqsolve = new vcs_MultiPhaseEquil(&s, printLvlSub); int err = eqsolve->equilibrate(ixy, estimateEquil, printLvlSub, tol, maxsteps, loglevel); if (err != 0) { retn = -1; } // hard code a csv output file. if (printLvl > 0) { string reportFile = "vcs_equilibrate_res.csv"; if (counter > 0) { reportFile = "vcs_equilibrate_res_" + int2str(counter) + ".csv"; } eqsolve->reportCSV(reportFile); counter++; } delete eqsolve; } catch (CanteraError& e) { e.save(); retn = -1; throw e; } } else if (solver == 1) { if (ixy == TP || ixy == HP || ixy == SP || ixy == TV) { try { s.equilibrate(ixy, tol, maxsteps, maxiter, loglevel); return 0; } catch (CanteraError& e) { e.save(); throw e; } } else { throw CanteraError("equilibrate","unsupported option"); } } else { throw CanteraError("vcs_equilibrate_1", "unknown solver"); } return retn; }
void testProblem() { double T = 273.15 + 352.0; vcs_timing_print_lvl = 0; // Create the phases std::auto_ptr<ThermoPhase> LiSi_solid(newPhase("Li7Si3_ls.xml", "Li7Si3_and_Interstitials(S)")); std::auto_ptr<ThermoPhase> Li_liq(newPhase("Li_Liquid.xml", "Li(L)")); FixedChemPotSSTP LiFixed("Li", -2.3E7); MargulesVPSSTP salt("LiKCl_liquid.xml", "MoltenSalt_electrolyte"); // set states vector_fp x(salt.nSpecies(), 0); x[0] = 0.7; x[1] = 1.0 - x[0]; salt.setState_TPX(T, OneAtm, &x[0]); LiSi_solid->setState_TP(T, OneAtm); int ee = static_cast<int>(LiSi_solid->nElements()); printf("Number of elements = %d\n", ee); LiFixed.setState_TP(T, OneAtm); double um[20]; LiFixed.getChemPotentials(um); printf(" chem pot = %g\n", um[0]); double volts = 1.635; // has some Fe in it // test suite double dg_corr = - volts * Faraday; printf("dg_corr = %g\n", dg_corr); Li_liq->getChemPotentials(um); double um_li_chempot = um[0] + dg_corr; printf("um_li_chempot = %g\n", um_li_chempot); LiFixed.setChemicalPotential(um_li_chempot); MultiPhase mmm; mmm.addPhase(&salt, 10.); mmm.addPhase(LiSi_solid.get(), 1.); mmm.addPhase(&LiFixed, 100.); int printLvl = 3; int estimateEquil = 0; mmm.equilibrate("TP", "vcs", 1e-9, 50000, 100, estimateEquil, printLvl); std::cout << mmm << std::endl; appdelete(); }
void ThermoPhase::equilibrate(const std::string& XY, const std::string& solver, double rtol, int max_steps, int max_iter, int estimate_equil, int log_level) { if (solver == "auto" || solver == "element_potential") { vector_fp initial_state; saveState(initial_state); debuglog("Trying ChemEquil solver\n", log_level); try { ChemEquil E; E.options.maxIterations = max_steps; E.options.relTolerance = rtol; bool use_element_potentials = (estimate_equil == 0); int ret = E.equilibrate(*this, XY.c_str(), use_element_potentials, log_level-1); if (ret < 0) { throw CanteraError("ThermoPhase::equilibrate", "ChemEquil solver failed. Return code: {}", ret); } setElementPotentials(E.elementPotentials()); debuglog("ChemEquil solver succeeded\n", log_level); return; } catch (std::exception& err) { debuglog("ChemEquil solver failed.\n", log_level); debuglog(err.what(), log_level); restoreState(initial_state); if (solver == "auto") { } else { throw; } } } if (solver == "auto" || solver == "vcs" || solver == "gibbs") { MultiPhase M; M.addPhase(this, 1.0); M.init(); M.equilibrate(XY, solver, rtol, max_steps, max_iter, estimate_equil, log_level); return; } if (solver != "auto") { throw CanteraError("ThermoPhase::equilibrate", "Invalid solver specified: '{}'", solver); } }
/* * Set a multiphase mixture to a state of chemical equilibrium. * This is the top-level driver for multiphase equilibrium. It * doesn't do much more than call the equilibrate method of class * MultiPhase, except that it adds some messages to the logfile, * if loglevel is set > 0. * * @ingroup equil */ doublereal equilibrate(MultiPhase& s, const char* XY, doublereal tol, int maxsteps, int maxiter, int loglevel) { if (loglevel > 0) { beginLogGroup("equilibrate",loglevel); addLogEntry("multiphase equilibrate function"); beginLogGroup("arguments"); addLogEntry("XY",XY); addLogEntry("tol",tol); addLogEntry("maxsteps",maxsteps); addLogEntry("maxiter",maxiter); addLogEntry("loglevel",loglevel); endLogGroup("arguments"); } s.init(); int ixy = _equilflag(XY); if (ixy == TP || ixy == HP || ixy == SP || ixy == TV) { try { double err = s.equilibrate(ixy, tol, maxsteps, maxiter, loglevel); if (loglevel > 0) { addLogEntry("Success. Error",err); endLogGroup("equilibrate"); } return err; } catch (CanteraError &err) { if (loglevel > 0) { addLogEntry("Failure.",lastErrorMessage()); endLogGroup("equilibrate"); } throw err; } } else { if (loglevel > 0) { addLogEntry("multiphase equilibrium can be done only for TP, HP, SP, or TV"); endLogGroup("equilibrate"); } throw CanteraError("equilibrate","unsupported option"); return -1.0; } return 0.0; }
/* * This function uses the vcs_MultiPhaseEquil interface to the * vcs solver. * The function uses the element abundance vector that is * currently consistent with the composition within the phases * themselves. Two other thermodynamic quantities, determined by the * XY string, are held constant during the equilibration. * * @param s The object to set to an equilibrium state * * @param XY An integer specifying the two properties to be held * constant. * * @param estimateEquil integer indicating whether the solver * should estimate its own initial condition. * If 0, the initial mole fraction vector * in the %ThermoPhase object is used as the * initial condition. * If 1, the initial mole fraction vector * is used if the element abundances are * satisfied. * if -1, the initial mole fraction vector * is thrown out, and an estimate is * formulated. * * @param printLvl Determines the amount of printing that * gets sent to stdout from the vcs package * (Note, you may have to compile with debug * flags to get some printing). * * @param maxsteps The maximum number of steps to take to find * the solution. * * @param maxiter For the MultiPhaseEquil solver only, this is * the maximum number of outer temperature or * pressure iterations to take when T and/or P is * not held fixed. * * @param loglevel Controls amount of diagnostic output. loglevel * = 0 suppresses diagnostics, and increasingly-verbose * messages are written as loglevel increases. The * messages are written to a file in HTML format for viewing * in a web browser. @see HTML_logs * * @ingroup equilfunctions */ int vcs_equilibrate_1(MultiPhase& s, int ixy, int estimateEquil, int printLvl, int solver, doublereal tol, int maxsteps, int maxiter, int loglevel) { static int counter = 0; int retn = 1; beginLogGroup("equilibrate",loglevel); addLogEntry("multiphase equilibrate function"); beginLogGroup("arguments"); addLogEntry("XY",ixy); addLogEntry("tol",tol); addLogEntry("maxsteps",maxsteps); addLogEntry("maxiter",maxiter); addLogEntry("loglevel",loglevel); endLogGroup("arguments"); int printLvlSub = std::max(0, printLvl-1); s.init(); if (solver == 2) { try { VCSnonideal::vcs_MultiPhaseEquil* eqsolve = new VCSnonideal::vcs_MultiPhaseEquil(&s, printLvlSub); int err = eqsolve->equilibrate(ixy, estimateEquil, printLvlSub, tol, maxsteps, loglevel); if (err != 0) { retn = -1; addLogEntry("vcs_equilibrate Error - ", err); } else { addLogEntry("vcs_equilibrate Success - ", err); } endLogGroup("equilibrate"); // hard code a csv output file. if (printLvl > 0) { string reportFile = "vcs_equilibrate_res.csv"; if (counter > 0) { reportFile = "vcs_equilibrate_res_" + int2str(counter) + ".csv"; } eqsolve->reportCSV(reportFile); counter++; } delete eqsolve; } catch (CanteraError& e) { e.save(); retn = -1; addLogEntry("Failure.", lastErrorMessage()); endLogGroup("equilibrate"); throw e; } } else if (solver == 1) { if (ixy == TP || ixy == HP || ixy == SP || ixy == TV) { try { double err = s.equilibrate(ixy, tol, maxsteps, maxiter, loglevel); addLogEntry("Success. Error",err); endLogGroup("equilibrate"); return 0; } catch (CanteraError& e) { e.save(); addLogEntry("Failure.",lastErrorMessage()); endLogGroup("equilibrate"); throw e; } } else { addLogEntry("multiphase equilibrium can be done only for TP, HP, SP, or TV"); endLogGroup("equilibrate"); throw CanteraError("equilibrate","unsupported option"); //return -1.0; } } else { throw CanteraError("vcs_equilibrate_1", "unknown solver"); } return retn; }
int main(int argc, char** argv) { #if defined(_MSC_VER) && _MSC_VER < 1900 _set_output_format(_TWO_DIGIT_EXPONENT); #endif suppress_deprecation_warnings(); int numSucc = 0; int numFail = 0; int printLvl = 1; string inputFile = "HMW_NaCl.xml"; VCS_SOLVE::disableTiming(); /* * Process the command line arguments */ if (argc > 1) { string tok; for (int j = 1; j < argc; j++) { tok = string(argv[j]); if (tok[0] == '-') { int nopt = static_cast<int>(tok.size()); for (int n = 1; n < nopt; n++) { if (!strcmp(tok.c_str() + 1, "help_cmdfile")) { } else if (tok[n] == 'h') { printUsage(); exit(1); } else if (tok[n] == 'd') { printLvl = 2; int lvl = 2; if (j < (argc - 1)) { string tokla = string(argv[j+1]); if (strlen(tokla.c_str()) > 0) { lvl = atoi(tokla.c_str()); n = nopt - 1; j += 1; if (lvl >= 0) { printLvl = lvl; } } } } else { printUsage(); exit(1); } } } else if (inputFile == "HMW_NaCl.xml") { inputFile = tok; } else { printUsage(); exit(1); } } } try { int estimateEquil = -1; double T = 298.15; double pres = OneAtm; // Initialize the individual phases HMWSoln hmw(inputFile, ""); size_t kk = hmw.nSpecies(); vector_fp Xmol(kk, 0.0); size_t iH2OL = hmw.speciesIndex("H2O(L)"); Xmol[iH2OL] = 1.0; hmw.setState_TPX(T, pres, Xmol.data()); ThermoPhase* gas = newPhase("gas.xml"); kk = gas->nSpecies(); Xmol.resize(kk, 0.0); for (size_t i = 0; i < kk; i++) { Xmol[i] = 0.0; } size_t iN2 = gas->speciesIndex("N2"); Xmol[iN2] = 1.0; gas->setState_TPX(T, pres, Xmol.data()); StoichSubstance ss("NaCl_Solid.xml", ""); ss.setState_TP(T, pres); // Construct the multiphase object MultiPhase* mp = new MultiPhase(); mp->addPhase(&hmw, 2.0); mp->addPhase(gas, 4.0); mp->addPhase(&ss, 5.0); try { mp->equilibrate("TP", "vcs", 1e-9, 50000, 100, estimateEquil, printLvl); cout << *mp; numSucc++; } catch (CanteraError& err) { cout << *mp; std::cerr << err.what() << std::endl; cerr << "ERROR: MultiEquil equilibration step failed at " << " T = " << T << " Pres = " << pres << endl; cout << "ERROR: MultiEqiul equilibration step failed at " << " T = " << T << " Pres = " << pres << endl; exit(-1); } cout << "NUMBER OF SUCCESSES = " << numSucc << endl; cout << "NUMBER OF FAILURES = " << numFail << endl; return numFail; } catch (CanteraError& err) { std::cerr << err.what() << std::endl; cerr << "ERROR: program terminating due to unforeseen circumstances." << endl; return -1; } }