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;
}
Exemple #2
0
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();
}
int vcs_determine_PhaseStability(MultiPhase& s, int iphase,
                                 double& funcStab, int printLvl, int loglevel)
{
    int iStab = 0;
    static int counter = 0;
    int printLvlSub = std::max(0, printLvl-1);

    s.init();
    try {
        vcs_MultiPhaseEquil* eqsolve = new vcs_MultiPhaseEquil(&s, printLvlSub);
        iStab = eqsolve->determine_PhaseStability(iphase, funcStab, printLvlSub, loglevel);
        // hard code a csv output file.
        if (printLvl > 0) {
            string reportFile = "vcs_phaseStability.csv";
            if (counter > 0) {
                reportFile = "vcs_phaseStability_" + int2str(counter) + ".csv";
            }
            eqsolve->reportCSV(reportFile);
            counter++;
        }
        delete eqsolve;
    } catch (CanteraError& e) {
        throw e;
    }
    return iStab;
}
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);
    }
}
Exemple #5
0
  /*
   * 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; 
  }
TEST_F(OverconstrainedEquil, DISABLED_BasisOptimize2)
{
    setup("O H C N Ar");
    MultiPhase mphase;
    mphase.addPhase(gas.get(), 10.0);
    mphase.init();
    int usedZeroedSpecies = 0;
    std::vector<size_t> orderVectorSpecies;
    std::vector<size_t> orderVectorElements;

    bool doFormMatrix = true;
    vector_fp formRxnMatrix;

    size_t nc = BasisOptimize(&usedZeroedSpecies, doFormMatrix, &mphase,
                              orderVectorSpecies, orderVectorElements,
                              formRxnMatrix);
    ASSERT_EQ(1, (int) nc);
}
/*
 *
 *  @param s         The MultiPhase object to be set to an equilibrium state
 *  @param iphase    Phase index within the multiphase object to be
 *                   tested for stability.
 *  @param funcStab  Function value that tests equilibrium. > 0 indicates stable
 *                   < 0 indicates unstable
 *
 *  @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 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
 */
int vcs_determine_PhaseStability(MultiPhase& s, int iphase,
                                 double& funcStab, int printLvl, int loglevel)
{
    int iStab = 0;
    static int counter = 0;
    beginLogGroup("PhaseStability",loglevel);
    addLogEntry("multiphase phase stability function");
    beginLogGroup("arguments");
    addLogEntry("iphase",iphase);
    addLogEntry("loglevel",loglevel);
    endLogGroup("arguments");

    int printLvlSub = std::max(0, printLvl-1);

    s.init();
    try {
        VCSnonideal::vcs_MultiPhaseEquil* eqsolve = new VCSnonideal::vcs_MultiPhaseEquil(&s, printLvlSub);
        iStab = eqsolve->determine_PhaseStability(iphase, funcStab, printLvlSub, loglevel);
        if (iStab != 0) {
            addLogEntry("Phase is stable  - ", iphase);
        } else {
            addLogEntry("Phase is not stable - ", iphase);
        }
        endLogGroup("PhaseStability");
        // hard code a csv output file.
        if (printLvl > 0) {
            string reportFile = "vcs_phaseStability.csv";
            if (counter > 0) {
                reportFile = "vcs_phaseStability_" + int2str(counter) + ".csv";
            }
            eqsolve->reportCSV(reportFile);
            counter++;
        }
        delete eqsolve;
    } catch (CanteraError& e) {
        addLogEntry("Failure.", lastErrorMessage());
        endLogGroup("equilibrate");
        throw e;
    }
    return iStab;
}
/*
 *  Set a single-phase chemical solution to chemical equilibrium.
 *  This is a convenience function that uses one or the other of
 *  the two chemical equilibrium solvers.
 *
 *  @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 solver The equilibrium solver to use. If solver = 0,
 *                the ChemEquil solver will be used, and if
 *                solver = 1, the vcs_MultiPhaseEquil solver will
 *                be used (slower than ChemEquil,
 *                but more stable). If solver < 0 (default, then
 *                ChemEquil will be tried first, and if it fails
 *                vcs_MultiPhaseEquil will be tried.
 *
 *  @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
 */
int vcs_equilibrate(thermo_t& s, const char* XY,
                    int estimateEquil,  int printLvl,
                    int solver,
                    doublereal rtol, int maxsteps, int maxiter,
                    int loglevel)
{
    MultiPhase* m = 0;
    int retn = 1;
    int retnSub = 0;

    beginLogGroup("equilibrate", loglevel);
    // retry:
    addLogEntry("Single-phase equilibrate function");
    {
        beginLogGroup("arguments");
        addLogEntry("phase",s.id());
        addLogEntry("XY",XY);
        addLogEntry("solver",solver);
        addLogEntry("rtol",rtol);
        addLogEntry("maxsteps",maxsteps);
        addLogEntry("maxiter",maxiter);
        addLogEntry("loglevel",loglevel);
        endLogGroup("arguments");
    }

    if (solver == 2) {
        m = new MultiPhase;
        try {
            /*
             *  Set the kmoles of the phase to 1.0, arbitrarily.
             *  It actually doesn't matter.
             */
            m->addPhase(&s, 1.0);
            m->init();

            retn = vcs_equilibrate(*m, XY, estimateEquil, printLvl, solver,
                                   rtol, maxsteps, maxiter, loglevel);
            if (retn == 1) {
                addLogEntry("MultiPhaseEquil solver succeeded.");
            } else {
                addLogEntry("MultiPhaseEquil solver returned an error code: ", retn);
            }
            delete m;
        } catch (CanteraError& err) {
            err.save();
            addLogEntry("MultiPhaseEquil solver failed.");
            delete m;
            throw err;
        }
    } else if (solver == 1) {
        m = new MultiPhase;
        try {
            m->addPhase(&s, 1.0);
            m->init();
            (void) equilibrate(*m, XY, rtol, maxsteps, maxiter, loglevel-1);
            if (loglevel > 0) {
                addLogEntry("MultiPhaseEquil solver succeeded.");
            }
            delete m;
            retn = 1;
        } catch (CanteraError& err) {
            err.save();
            if (loglevel > 0) {
                addLogEntry("MultiPhaseEquil solver failed.");
            }
            delete m;
            throw err;
        }
    } else if (solver == 0) {
        ChemEquil* e = new ChemEquil;
        try {
            e->options.maxIterations = maxsteps;
            e->options.relTolerance = rtol;
            bool useThermoPhaseElementPotentials = false;
            if (estimateEquil == 0) {
                useThermoPhaseElementPotentials = true;
            }
            retnSub = e->equilibrate(s, XY,
                                     useThermoPhaseElementPotentials, loglevel-1);
            if (retnSub < 0) {
                if (loglevel > 0) {
                    addLogEntry("ChemEquil solver failed.");
                }
                delete e;
                throw CanteraError("equilibrate",
                                   "ChemEquil equilibrium solver failed");
            }
            retn = 1;
            s.setElementPotentials(e->elementPotentials());
            delete e;
            if (loglevel > 0) {
                addLogEntry("ChemEquil solver succeeded.");
            }
        } catch (CanteraError& err) {
            err.save();
            if (loglevel > 0) {
                addLogEntry("ChemEquil solver failed.");
            }
            delete e;
            throw err;
        }
    } else {
        throw CanteraError("vcs_equilibrate",
                           "unknown solver");
    }

    /*
     * We are here only for a success
     */
    endLogGroup("equilibrate");
    return retn;
}
/*
 *  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;
}
Exemple #10
0
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;
    }
}
int vcs_equilibrate(thermo_t& s, const char* XY,
                    int estimateEquil,  int printLvl,
                    int solver,
                    doublereal rtol, int maxsteps, int maxiter,
                    int loglevel)
{
    warn_deprecated("vcs_equilibrate", "Use ThermoPhase::equilibrate instead. "
        "To be removed after Cantera 2.2.");
    MultiPhase* m = 0;
    int retn = 1;

    if (solver == 2) {
        m = new MultiPhase;
        try {
            /*
             *  Set the kmoles of the phase to 1.0, arbitrarily.
             *  It actually doesn't matter.
             */
            m->addPhase(&s, 1.0);
            m->init();

            retn = vcs_equilibrate(*m, XY, estimateEquil, printLvl, solver,
                                   rtol, maxsteps, maxiter, loglevel);
            delete m;
        } catch (CanteraError& err) {
            err.save();
            delete m;
            throw err;
        }
    } else if (solver == 1) {
        m = new MultiPhase;
        try {
            m->addPhase(&s, 1.0);
            m->init();
            (void) equilibrate(*m, XY, rtol, maxsteps, maxiter, loglevel-1);
            delete m;
            retn = 1;
        } catch (CanteraError& err) {
            err.save();
            delete m;
            throw err;
        }
    } else if (solver == 0) {
        ChemEquil* e = new ChemEquil;
        try {
            e->options.maxIterations = maxsteps;
            e->options.relTolerance = rtol;
            bool useThermoPhaseElementPotentials = false;
            if (estimateEquil == 0) {
                useThermoPhaseElementPotentials = true;
            }
            int retnSub = e->equilibrate(s, XY,
                                     useThermoPhaseElementPotentials, loglevel-1);
            if (retnSub < 0) {
                delete e;
                throw CanteraError("equilibrate",
                                   "ChemEquil equilibrium solver failed");
            }
            retn = 1;
            s.setElementPotentials(e->elementPotentials());
            delete e;
        } catch (CanteraError& err) {
            err.save();
            delete e;
            throw err;
        }
    } else {
        throw CanteraError("vcs_equilibrate",
                           "unknown solver");
    }

    /*
     * We are here only for a success
     */
    return retn;
}
Exemple #12
0
  /*
   *  Set a single-phase chemical solution to chemical equilibrium.
   *  This is a convenience function that uses one or the other of
   *  the two chemical equilibrium solvers.
   * 
   *  @param s The object to set to an equilibrium state
   * 
   *  @param XY An integer specifying the two properties to be held
   *  constant.
   * 
   *  @param solver The equilibrium solver to use. If solver = 0,
   *  the ChemEquil solver will be used, and if solver = 1, the
   *  MultiPhaseEquil solver will be used (slower than ChemEquil,
   *  but more stable). If solver < 0 (default, then ChemEquil will
   *  be tried first, and if it fails MultiPhaseEquil will be tried.
   * 
   *  @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 equil
   */
  int equilibrate(thermo_t& s, const char* XY, int solver,
		  doublereal rtol, int maxsteps, int maxiter, int loglevel) {
    MultiPhase* m = 0;
    ChemEquil* e = 0;
    bool redo = true;
    int retn = -1;
    int nAttempts = 0;
    int retnSub = 0;
  

    if (loglevel > 0) {
      beginLogGroup("equilibrate", loglevel);
      addLogEntry("Single-phase equilibrate function");
      {
	beginLogGroup("arguments");
	addLogEntry("phase",s.id());
	addLogEntry("XY",XY);
	addLogEntry("solver",solver);
	addLogEntry("rtol",rtol);
	addLogEntry("maxsteps",maxsteps);
	addLogEntry("maxiter",maxiter);
	addLogEntry("loglevel",loglevel);
	endLogGroup("arguments");
      }
    }
    while (redo) {
      if (solver >= 2) {
#ifdef WITH_VCSNONIDEAL
	int printLvlSub = 0;
	int estimateEquil = 0;
	m = new MultiPhase;
	try { 
	  m->addPhase(&s, 1.0);
	  m->init();
	  nAttempts++;
	  vcs_equilibrate(*m, XY, estimateEquil, printLvlSub, solver,
			  rtol, maxsteps, maxiter, loglevel-1); 
	  redo = false;
          if (loglevel > 0) 
	    addLogEntry("VCSnonideal solver succeeded.");
	  delete m;
	  retn = nAttempts;
	}
	catch (CanteraError &err) {
	  if (loglevel > 0) 
	    addLogEntry("VCSnonideal solver failed.");
	  delete m;
	  if (nAttempts < 2) {
	    if (loglevel > 0) 
	      addLogEntry("Trying single phase ChemEquil solver.");
	    solver = -1;
	  } 
	  else {
	    if (loglevel > 0) 
	      endLogGroup("equilibrate");
	    throw err;
	  }
	}
#else
	throw CanteraError("equilibrate", 
			   "VCSNonIdeal solver called, but not compiled");
#endif
      } else if (solver == 1) {
	m = new MultiPhase;
	try { 
	  m->addPhase(&s, 1.0);
	  m->init();
	  nAttempts++;
	  (void) equilibrate(*m, XY, rtol, maxsteps, maxiter, loglevel-1); 
	  redo = false;
          if (loglevel > 0) 
	    addLogEntry("MultiPhaseEquil solver succeeded.");
	  delete m;
	  retn = nAttempts;
	}
	catch (CanteraError &err) {
	  if (loglevel > 0) 
	    addLogEntry("MultiPhaseEquil solver failed.");
	  delete m;
	  if (nAttempts < 2) {
	    if (loglevel > 0) 
	      addLogEntry("Trying single phase ChemEquil solver.");
	    solver = -1;
	  } 
	  else {
	    if (loglevel > 0) 
	      endLogGroup("equilibrate");
	    throw err;
	  }
	}
      }
      else {        // solver <= 0
	/*
	 * Call the element potential solver
	 */
	e = new ChemEquil;
	try {
	  e->options.maxIterations = maxsteps;
	  e->options.relTolerance = rtol;
	  nAttempts++;
          bool useThermoPhaseElementPotentials = true;
	  retnSub = e->equilibrate(s,XY,
                                   useThermoPhaseElementPotentials, loglevel-1);
	  if (retnSub < 0) {
	    if (loglevel > 0) 
	      addLogEntry("ChemEquil solver failed.");
	    if (nAttempts < 2) {
	      if (loglevel > 0) 
		addLogEntry("Trying MultiPhaseEquil solver.");
	      solver = 1;
	    } else {
	      throw CanteraError("equilibrate", 
				 "Both equilibrium solvers failed");
	    }
	  }
	  retn = nAttempts;
	  s.setElementPotentials(e->elementPotentials());
	  redo = false;
	  delete e;
          if (loglevel > 0) 
	    addLogEntry("ChemEquil solver succeeded.");
	}

	catch (CanteraError &err) {
	  delete e;
          if (loglevel > 0) 
	    addLogEntry("ChemEquil solver failed.");
	  // If ChemEquil fails, try the MultiPhase solver
	  if (solver < 0) {
	    if (loglevel > 0) 
	      addLogEntry("Trying MultiPhaseEquil solver.");
	    solver = 1;
	  }
	  else {
	    redo = false;
            if (loglevel > 0) 
	      endLogGroup("equilibrate");
	    throw err;
	  }
	}
      } 
    } // while (redo)
    /*
     * We are here only for a success
     */
    if (loglevel > 0) 
      endLogGroup("equilibrate");
    return retn;
  }
Exemple #13
0
int equilibrate(thermo_t& s, const char* XY, int solver,
                doublereal rtol, int maxsteps, int maxiter, int loglevel)
{
    bool redo = true;
    int retn = -1;
    int nAttempts = 0;
    int retnSub = 0;

    if (loglevel > 0) {
        beginLogGroup("equilibrate", loglevel);
        addLogEntry("Single-phase equilibrate function");
        {
            beginLogGroup("arguments");
            addLogEntry("phase",s.id());
            addLogEntry("XY",XY);
            addLogEntry("solver",solver);
            addLogEntry("rtol",rtol);
            addLogEntry("maxsteps",maxsteps);
            addLogEntry("maxiter",maxiter);
            addLogEntry("loglevel",loglevel);
            endLogGroup("arguments");
        }
    }
    while (redo) {
        if (solver >= 2) {
            int printLvlSub = 0;
            int estimateEquil = 0;
            try {
                MultiPhase m;
                m.addPhase(&s, 1.0);
                m.init();
                nAttempts++;
                vcs_equilibrate(m, XY, estimateEquil, printLvlSub, solver,
                                rtol, maxsteps, maxiter, loglevel-1);
                redo = false;
                if (loglevel > 0) {
                    addLogEntry("VCSnonideal solver succeeded.");
                }
                retn = nAttempts;
            } catch (CanteraError& err) {
                err.save();
                if (loglevel > 0) {
                    addLogEntry("VCSnonideal solver failed.");
                }
                if (nAttempts < 2) {
                    if (loglevel > 0) {
                        addLogEntry("Trying single phase ChemEquil solver.");
                    }
                    solver = -1;
                } else {
                    if (loglevel > 0) {
                        endLogGroup("equilibrate");
                    }
                    throw err;
                }
            }
        } else if (solver == 1) {
            try {
                MultiPhase m;
                m.addPhase(&s, 1.0);
                m.init();
                nAttempts++;
                equilibrate(m, XY, rtol, maxsteps, maxiter, loglevel-1);
                redo = false;
                if (loglevel > 0) {
                    addLogEntry("MultiPhaseEquil solver succeeded.");
                }
                retn = nAttempts;
            } catch (CanteraError& err) {
                err.save();
                if (loglevel > 0) {
                    addLogEntry("MultiPhaseEquil solver failed.");
                }
                if (nAttempts < 2) {
                    if (loglevel > 0) {
                        addLogEntry("Trying single phase ChemEquil solver.");
                    }
                    solver = -1;
                } else {
                    if (loglevel > 0) {
                        endLogGroup("equilibrate");
                    }
                    throw err;
                }
            }
        } else {      // solver <= 0
            /*
             * Call the element potential solver
             */
            try {
                ChemEquil e;
                e.options.maxIterations = maxsteps;
                e.options.relTolerance = rtol;
                nAttempts++;
                bool useThermoPhaseElementPotentials = true;
                retnSub = e.equilibrate(s, XY, useThermoPhaseElementPotentials,
                                        loglevel-1);
                if (retnSub < 0) {
                    if (loglevel > 0) {
                        addLogEntry("ChemEquil solver failed.");
                    }
                    if (nAttempts < 2) {
                        if (loglevel > 0) {
                            addLogEntry("Trying MultiPhaseEquil solver.");
                        }
                        solver = 1;
                    } else {
                        throw CanteraError("equilibrate",
                                           "Both equilibrium solvers failed");
                    }
                }
                retn = nAttempts;
                s.setElementPotentials(e.elementPotentials());
                redo = false;
                if (loglevel > 0) {
                    addLogEntry("ChemEquil solver succeeded.");
                }
            }

            catch (CanteraError& err) {
                err.save();
                if (loglevel > 0) {
                    addLogEntry("ChemEquil solver failed.");
                }
                // If ChemEquil fails, try the MultiPhase solver
                if (solver < 0) {
                    if (loglevel > 0) {
                        addLogEntry("Trying MultiPhaseEquil solver.");
                    }
                    solver = 1;
                } else {
                    redo = false;
                    if (loglevel > 0) {
                        endLogGroup("equilibrate");
                    }
                    throw err;
                }
            }
        }
    } // while (redo)
    /*
     * We are here only for a success
     */
    if (loglevel > 0) {
        endLogGroup("equilibrate");
    }
    return retn;
}