Пример #1
0
    void OutletRes1D::
    init() { 
        _init(1); 
       // set bounds (dummy)
        const doublereal lower = -1.0;
        const doublereal upper = 1.0;
        setBounds(1, &lower, 1, &upper);

        // set tolerances
        const doublereal rtol = 1e-4;
        const doublereal atol = 1.e-4;
        setTolerances(1, &rtol, 1, &atol);

        if (m_flow_left) {
            m_flow = m_flow_left;
        }
        else if (m_flow_right) {
            m_flow = m_flow_right;
        }
        else {
            throw CanteraError("OutletRes1D::init","no flow!");
        }

        m_nsp = m_flow->nComponents() - 4;
        m_yres.resize(m_nsp, 0.0);
        if (m_xstr != "") 
            setMoleFractions(m_xstr);
        else
            m_yres[0] = 1.0;
    }
void Inlet1D::init()
{
    _init(2);

    setBounds(0, -1e5, 1e5); // mdot
    setBounds(1, 200.0, 1e5); // T

    // if a flow domain is present on the left, then this must be a right inlet.
    // Note that an inlet object can only be a terminal object - it cannot have
    // flows on both the left and right
    if (m_flow_left) {
        m_ilr = RightInlet;
        m_flow = m_flow_left;
    } else if (m_flow_right) {
        m_ilr = LeftInlet;
        m_flow = m_flow_right;
    } else {
        throw CanteraError("Inlet1D::init","no flow!");
    }

    // components = u, V, T, lambda, + mass fractions
    m_nsp = m_flow->nComponents() - 4;
    m_yin.resize(m_nsp, 0.0);
    if (m_xstr != "") {
        setMoleFractions(m_xstr);
    } else {
        m_yin[0] = 1.0;
    }
}
Пример #3
0
void OutletRes1D::
init()
{
    _init(1);
    // set bounds (dummy)
    setBounds(0, -1.0, 1.0);

    // set tolerances
    setSteadyTolerances(1e-4, 1e-4);
    setTransientTolerances(1e-4, 1e-4);

    if (m_flow_left) {
        m_flow = m_flow_left;
    } else if (m_flow_right) {
        m_flow = m_flow_right;
    } else {
        throw CanteraError("OutletRes1D::init","no flow!");
    }

    m_nsp = m_flow->nComponents() - 4;
    m_yres.resize(m_nsp, 0.0);
    if (m_xstr != "") {
        setMoleFractions(m_xstr);
    } else {
        m_yres[0] = 1.0;
    }
}
Пример #4
0
/*
 * setMolalities():
 *   We are supplied with the molalities of all of the
 *   solute species. We then calculate the mole fractions of all
 *   species and update the ThermoPhase object.
 *
 *     m_i = (n_i) / (W_o/1000 * n_o_p)
 *
 *    where M_o is the molecular weight of the solvent
 *    n_o is the mole fraction of the solvent
 *    n_i is the mole fraction of the solute.
 *    n_o_p = max (n_o_min, n_o)
 *    n_o_min = minimum mole fraction of solvent allowed
 *              in the denominator.
 */
void MolalityVPSSTP::setMolalities(const doublereal* const molal)
{

    double Lsum = 1.0 / m_Mnaught;
    for (size_t k = 1; k < m_kk; k++) {
        m_molalities[k] = molal[k];
        Lsum += molal[k];
    }
    double tmp = 1.0 / Lsum;
    m_molalities[m_indexSolvent] = tmp / m_Mnaught;
    double sum = m_molalities[m_indexSolvent];
    for (size_t k = 1; k < m_kk; k++) {
        m_molalities[k] = tmp * molal[k];
        sum += m_molalities[k];
    }
    if (sum != 1.0) {
        tmp = 1.0 / sum;
        for (size_t k = 0; k < m_kk; k++) {
            m_molalities[k] *= tmp;
        }
    }
    setMoleFractions(DATA_PTR(m_molalities));
    /*
     * Essentially we don't trust the input: We calculate
     * the molalities from the mole fractions that we
     * just obtained.
     */
    calcMolalities();
}
Пример #5
0
void Phase::setMoleFractionsByName(const compositionMap& xMap)
{
    size_t kk = nSpecies();
    vector_fp mf(kk, 0.0);
    for (size_t k = 0; k < kk; k++) {
        mf[k] = std::max(getValue(xMap, speciesName(k), 0.0), 0.0);
    }
    setMoleFractions(&mf[0]);
}
Пример #6
0
 void Phase::setMoleFractionsByName(compositionMap& xMap) {
   int kk = nSpecies();
   doublereal x;
   vector_fp mf(kk, 0.0);
   for (int k = 0; k < kk; k++) {
     x = xMap[speciesName(k)];
     if (x > 0.0) mf[k] = x;
   }
   setMoleFractions(&mf[0]);
 }
Пример #7
0
void Phase::setMoleFractionsByName(const compositionMap& xMap)
{
    vector_fp mf(m_kk, 0.0);
    for (const auto& sp : xMap) {
        try {
            mf[getValue(m_speciesIndices, sp.first)] = sp.second;
        } catch (std::out_of_range&) {
            throw CanteraError("Phase::setMoleFractionsByName",
                               "Unknown species '{}'", sp.first);
        }
    }
    setMoleFractions(&mf[0]);
}
void LatticeSolidPhase::setLatticeMoleFractionsByName(int nn, const std::string& x)
{
    m_lattice[nn]->setMoleFractionsByName(x);
    size_t loc = 0;
    for (size_t n = 0; n < m_lattice.size(); n++) {
        size_t nsp = m_lattice[n]->nSpecies();
        double ndens = m_lattice[n]->molarDensity();
        for (size_t k = 0; k < nsp; k++) {
            m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
            loc++;
        }
    }
    setMoleFractions(m_x.data());
}
Пример #9
0
 void LatticeSolidPhase::setLatticeMoleFractions(int nn, 
     string x) {
     m_lattice[nn]->setMoleFractionsByName(x);
     int n, k, loc=0, nsp;
     doublereal ndens;
     for (n = 0; n < m_nlattice; n++) {
         nsp = m_lattice[n]->nSpecies();
         ndens = m_lattice[n]->molarDensity();
         for (k = 0; k < nsp; k++) {
             m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
             loc++;
         }
     }
     setMoleFractions(DATA_PTR(m_x));
 }
Пример #10
0
    void LatticeSolidPhase::initThermo() {
        m_kk = nSpecies();
        m_mm = nElements();
        m_x.resize(m_kk);
        int n, nsp, k, loc = 0;
        doublereal ndens;
        m_molar_density = 0.0;
        for (n = 0; n < m_nlattice; n++) {
            nsp = m_lattice[n]->nSpecies();
            ndens = m_lattice[n]->molarDensity();
            for (k = 0; k < nsp; k++) {
                m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
                loc++;
            }
            m_molar_density += ndens;
        }
        setMoleFractions(DATA_PTR(m_x));

//          const vector<string>& spnames = speciesNames();
//          int n, k, kl, namesize;
//          int nl = m_sitedens.size();
//          string s;
//          m_lattice.resize(m_kk,-1);
//          vector_fp conc(m_kk, 0.0);

//          compositionMap xx;
//          for (n = 0; n < nl; n++) {
//              for (k = 0; k < m_kk; k++) { 
//                  xx[speciesName(k)] = -1.0;
//              }
//              parseCompString(m_sp[n], xx);
//              for (k = 0; k < m_kk; k++) { 
//                  if (xx[speciesName(k)] != -1.0) {
//                      conc[k] = m_sitedens[n]*xx[speciesName(k)];
//                      m_lattice[k] = n;
//                  }
//              }

//          }
//          for (k = 0; k < m_kk; k++) {
//              if (m_lattice[k] == -1) {
//                  throw CanteraError("LatticeSolidPhase::"
//                      "setParametersFromXML","Species "+speciesName(k)
//                      +" not a member of any lattice.");
//              }                    
//          }
//          setMoleFractions(DATA_PTR(conc));
    }
Пример #11
0
void LatticeSolidPhase::initThermo()
{
    initLengths();
    size_t nsp, loc = 0;
    for (size_t n = 0; n < m_nlattice; n++) {
        nsp = m_lattice[n]->nSpecies();
        lkstart_[n] = loc;
        for (size_t k = 0; k < nsp; k++) {
            m_x[loc] =m_lattice[n]->moleFraction(k) / (double) m_nlattice;
            loc++;
        }
        lkstart_[n+1] = loc;
    }
    setMoleFractions(DATA_PTR(m_x));
    ThermoPhase::initThermo();
}
void LatticeSolidPhase::initThermo()
{
    size_t kk = 0;
    size_t kstart = 0;
    lkstart_.resize(m_lattice.size() + 1);
    size_t loc = 0;

    for (size_t n = 0; n < m_lattice.size(); n++) {
        LatticePhase* lp = m_lattice[n];
        vector_fp constArr(lp->nElements());
        const vector_fp& aws = lp->atomicWeights();
        for (size_t es = 0; es < lp->nElements(); es++) {
            addElement(lp->elementName(es), aws[es], lp->atomicNumber(es),
                       lp->entropyElement298(es), lp->elementType(es));
        }
        kstart = kk;

        for (size_t k = 0; k < lp->nSpecies(); k++) {
            addSpecies(lp->species(k));
            kk++;
        }
        // Add in the lattice stoichiometry constraint
        if (n > 0) {
            string econ = fmt::format("LC_{}_{}", n, id());
            size_t m = addElement(econ, 0.0, 0, 0.0, CT_ELEM_TYPE_LATTICERATIO);
            size_t mm = nElements();
            size_t nsp0 = m_lattice[0]->nSpecies();
            for (size_t k = 0; k < nsp0; k++) {
                m_speciesComp[k * mm + m] = -theta_[0];
            }
            for (size_t k = 0; k < lp->nSpecies(); k++) {
                size_t ks = kstart + k;
                m_speciesComp[ks * mm + m] = theta_[n];
            }
        }
        size_t nsp = m_lattice[n]->nSpecies();
        lkstart_[n] = loc;
        for (size_t k = 0; k < nsp; k++) {
            m_x[loc] =m_lattice[n]->moleFraction(k) / (double) m_lattice.size();
            loc++;
        }
        lkstart_[n+1] = loc;
    }

    setMoleFractions(m_x.data());
    ThermoPhase::initThermo();
}
Пример #13
0
 /*
  * @internal Initialize. This method is provided to allow
  * subclasses to perform any initialization required after all
  * species have been added. For example, it might be used to
  * resize internal work arrays that must have an entry for
  * each species.  The base class implementation does nothing,
  * and subclasses that do not require initialization do not
  * need to overload this method.  When importing a CTML phase
  * description, this method is called just prior to returning
  * from function importPhase.
  *
  * Inheriting objects should call this function
  *
  * @see importCTML.cpp
  */
 void SingleSpeciesTP::initThermo() {
   /*
    * Check to make sure that there is one and only one species
    * in this phase.
    */
   if (m_kk != 1) {
     err("singleSpeciesTP ERROR m_kk != 1");
   }
   /*
    *  Make sure the species mole fraction is equal to 1.0;
    */
   double x = 1.0;
   setMoleFractions(&x);
   /*
    * Call the base class initThermo object.
    */
   ThermoPhase::initThermo();
 }
Пример #14
0
    void Inlet1D::
    init() {

        _init(2);

        // set bounds (mdot, T)
        const doublereal lower[2] = {-1.0e5, 200.0};
        const doublereal upper[2] = {1.0e5, 1.e5};
        setBounds(2, lower, 2, upper);

        // set tolerances
        vector_fp rtol(2, 1e-4);
        vector_fp atol(2, 1.e-5);
        setTolerances(2, DATA_PTR(rtol), 2, DATA_PTR(atol));

        // if a flow domain is present on the left, then this must be
        // a right inlet. Note that an inlet object can only be a
        // terminal object - it cannot have flows on both the left and
        // right
        if (m_flow_left) {
            m_ilr = RightInlet;
            m_flow = m_flow_left;
        }
        else if (m_flow_right) {
            m_ilr = LeftInlet;
            m_flow = m_flow_right;
        }
        else {
            throw CanteraError("Inlet1D::init","no flow!");
        }
        
        // components = u, V, T, lambda, + mass fractions
        m_nsp = m_flow->nComponents() - 4;
        m_yin.resize(m_nsp, 0.0);
        if (m_xstr != "") 
            setMoleFractions(m_xstr);
        else
            m_yin[0] = 1.0;
    }
Пример #15
0
void Phase::setState_RX(doublereal rho, doublereal* x)
{
    setMoleFractions(x);
    setDensity(rho);
}
Пример #16
0
void Phase::setState_TX(doublereal t, doublereal* x)
{
    setTemperature(t);
    setMoleFractions(x);
}
Пример #17
0
void Phase::setState_TNX(doublereal t, doublereal n, const doublereal* x)
{
    setMoleFractions(x);
    setTemperature(t);
    setMolarDensity(n);
}
Пример #18
0
void Phase::setState_TRX(doublereal t, doublereal dens, const doublereal* x)
{
    setMoleFractions(x);
    setTemperature(t);
    setDensity(dens);
}
void MolalityVPSSTP::setMolalitiesByName(const compositionMap& mMap)
{
    // HKM -> Might need to be more complicated here, setting neutrals so that
    //        the existing mole fractions are preserved.

    // Get a vector of mole fractions
    vector_fp mf(m_kk, 0.0);
    getMoleFractions(mf.data());
    double xmolSmin = std::max(mf[m_indexSolvent], m_xmolSolventMIN);
    for (size_t k = 0; k < m_kk; k++) {
        double mol_k = getValue(mMap, speciesName(k), 0.0);
        if (mol_k > 0) {
            mf[k] = mol_k * m_Mnaught * xmolSmin;
        }
    }

    // check charge neutrality
    size_t largePos = npos;
    double cPos = 0.0;
    size_t largeNeg = npos;
    double cNeg = 0.0;
    double sum = 0.0;
    for (size_t k = 0; k < m_kk; k++) {
        double ch = charge(k);
        if (mf[k] > 0.0) {
            if (ch > 0.0 && ch * mf[k] > cPos) {
                largePos = k;
                cPos = ch * mf[k];
            }
            if (ch < 0.0 && fabs(ch) * mf[k] > cNeg) {
                largeNeg = k;
                cNeg = fabs(ch) * mf[k];
            }
        }
        sum += mf[k] * ch;
    }
    if (sum != 0.0) {
        if (sum > 0.0) {
            if (cPos > sum) {
                mf[largePos] -= sum / charge(largePos);
            } else {
                throw CanteraError("MolalityVPSSTP:setMolalitiesbyName",
                                   "unbalanced charges");
            }
        } else {
            if (cNeg > (-sum)) {
                mf[largeNeg] -= (-sum) / fabs(charge(largeNeg));
            } else {
                throw CanteraError("MolalityVPSSTP:setMolalitiesbyName",
                                   "unbalanced charges");
            }
        }
    }
    sum = 0.0;
    for (size_t k = 0; k < m_kk; k++) {
        sum += mf[k];
    }
    sum = 1.0/sum;
    for (size_t k = 0; k < m_kk; k++) {
        mf[k] *= sum;
    }
    setMoleFractions(mf.data());

    // After we formally set the mole fractions, we calculate the molalities
    // again and store it in this object.
    calcMolalities();
}
Пример #20
0
/*
 * setMolalitiesByName()
 *
 *  This routine sets the molalities by name
 *  HKM -> Might need to be more complicated here, setting
 *         neutrals so that the existing mole fractions are
 *         preserved.
 */
void MolalityVPSSTP::setMolalitiesByName(compositionMap& mMap)
{
    size_t kk = nSpecies();
    doublereal x;
    /*
     * Get a vector of mole fractions
     */
    vector_fp mf(kk, 0.0);
    getMoleFractions(DATA_PTR(mf));
    double xmolS = mf[m_indexSolvent];
    double xmolSmin = std::max(xmolS, m_xmolSolventMIN);
    compositionMap::iterator p;
    for (size_t k = 0; k < kk; k++) {
        p = mMap.find(speciesName(k));
        if (p != mMap.end()) {
            x = mMap[speciesName(k)];
            if (x > 0.0) {
                mf[k] = x * m_Mnaught * xmolSmin;
            }
        }
    }
    /*
     * check charge neutrality
     */
    size_t largePos = npos;
    double cPos = 0.0;
    size_t largeNeg = npos;
    double cNeg = 0.0;
    double sum = 0.0;
    for (size_t k = 0; k < kk; k++) {
        double ch = charge(k);
        if (mf[k] > 0.0) {
            if (ch > 0.0) {
                if (ch * mf[k] > cPos) {
                    largePos = k;
                    cPos = ch * mf[k];
                }
            }
            if (ch < 0.0) {
                if (fabs(ch) * mf[k] > cNeg) {
                    largeNeg = k;
                    cNeg = fabs(ch) * mf[k];
                }
            }
        }
        sum += mf[k] * ch;
    }
    if (sum != 0.0) {
        if (sum > 0.0) {
            if (cPos > sum) {
                mf[largePos] -= sum / charge(largePos);
            } else {
                throw CanteraError("MolalityVPSSTP:setMolalitiesbyName",
                                   "unbalanced charges");
            }
        } else {
            if (cNeg > (-sum)) {
                mf[largeNeg] -= (-sum) / fabs(charge(largeNeg));
            } else {
                throw CanteraError("MolalityVPSSTP:setMolalitiesbyName",
                                   "unbalanced charges");
            }
        }

    }
    sum = 0.0;
    for (size_t k = 0; k < kk; k++) {
        sum += mf[k];
    }
    sum = 1.0/sum;
    for (size_t k = 0; k < kk; k++) {
        mf[k] *= sum;
    }
    setMoleFractions(DATA_PTR(mf));
    /*
     * After we formally set the mole fractions, we
     * calculate the molalities again and store it in
     * this object.
     */
    calcMolalities();
}
void ThermoPhase::setState_PX(doublereal p, doublereal* x)
{
    setMoleFractions(x);
    setPressure(p);
}
void ThermoPhase::setState_RPX(doublereal rho, doublereal p, const doublereal* x)
{
    setMoleFractions(x);
    setState_RP(rho, p);
}
void ThermoPhase::setState_TPX(doublereal t, doublereal p, const doublereal* x)
{
    setMoleFractions(x);
    setState_TP(t,p);
}
Пример #24
0
void vcs_VolPhase::_updateLnActCoeffJac()
{
    double phaseTotalMoles = v_totalMoles;
    if (phaseTotalMoles < 1.0E-14) {
        phaseTotalMoles = 1.0;
    }

    /*
     * Evaluate the current base activity coefficients if necessary
     */
    if (!m_UpToDate_AC) {
        _updateActCoeff();
    }
    if (!TP_ptr) {
        return;
    }
    TP_ptr->getdlnActCoeffdlnN(m_numSpecies, &np_dLnActCoeffdMolNumber(0,0));
    for (size_t j = 0; j < m_numSpecies; j++) {
        double moles_j_base = phaseTotalMoles * Xmol_[j];
        double* const np_lnActCoeffCol = np_dLnActCoeffdMolNumber.ptrColumn(j);
        if (moles_j_base < 1.0E-200) {
            moles_j_base = 1.0E-7 * moles_j_base + 1.0E-13 * phaseTotalMoles + 1.0E-150;
        }
        for (size_t k = 0; k < m_numSpecies; k++) {
            np_lnActCoeffCol[k] = np_lnActCoeffCol[k] * phaseTotalMoles / moles_j_base;
        }
    }

    double deltaMoles_j = 0.0;
    // Make copies of ActCoeff and Xmol_ for use in taking differences
    std::vector<double> ActCoeff_Base(ActCoeff);
    std::vector<double> Xmol_Base(Xmol_);
    double TMoles_base = phaseTotalMoles;

    /*
     *  Loop over the columns species to be deltad
     */
    for (size_t j = 0; j < m_numSpecies; j++) {
        /*
         * Calculate a value for the delta moles of species j
         * -> Note Xmol_[] and Tmoles are always positive or zero
         *    quantities.
         */
        double moles_j_base = phaseTotalMoles * Xmol_Base[j];
        deltaMoles_j = 1.0E-7 * moles_j_base + 1.0E-13 * phaseTotalMoles + 1.0E-150;
        /*
         * Now, update the total moles in the phase and all of the
         * mole fractions based on this.
         */
        phaseTotalMoles = TMoles_base + deltaMoles_j;
        for (size_t k = 0; k < m_numSpecies; k++) {
            Xmol_[k] = Xmol_Base[k] * TMoles_base / phaseTotalMoles;
        }
        Xmol_[j] = (moles_j_base + deltaMoles_j) / phaseTotalMoles;

        /*
         * Go get new values for the activity coefficients.
         * -> Note this calls setState_PX();
         */
        _updateMoleFractionDependencies();
        _updateActCoeff();
        /*
         * Revert to the base case Xmol_, v_totalMoles
         */
        v_totalMoles = TMoles_base;
        Xmol_ = Xmol_Base;
    }
    /*
     * Go get base values for the activity coefficients.
     * -> Note this calls setState_TPX() again;
     * -> Just wanted to make sure that cantera is in sync
     *    with VolPhase after this call.
     */
    setMoleFractions(VCS_DATA_PTR(Xmol_Base));
    _updateMoleFractionDependencies();
    _updateActCoeff();
}
Пример #25
0
void WaterSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id)
{
    /*
     * Do initializations that don't depend on knowing the XML file
     */
    initThermo();
    /*
     * Calculate the molecular weight. Note while there may
     * be a very good calculated weight in the steam table
     * class, using this weight may lead to codes exhibiting
     * mass loss issues. We need to grab the elemental
     * atomic weights used in the Element class and calculate
     * a consistent H2O molecular weight based on that.
     */
    size_t nH = elementIndex("H");
    if (nH == npos) {
        throw CanteraError("WaterSSTP::initThermo",
                           "H not an element");
    }
    double mw_H = atomicWeight(nH);
    size_t nO = elementIndex("O");
    if (nO == npos) {
        throw CanteraError("WaterSSTP::initThermo",
                           "O not an element");
    }
    double mw_O = atomicWeight(nO);
    m_mw = 2.0 * mw_H + mw_O;
    setMolecularWeight(0,m_mw);
    double one = 1.0;
    setMoleFractions(&one);

    /*
     * Set the baseline
     */
    doublereal T = 298.15;
    Phase::setDensity(7.0E-8);
    Phase::setTemperature(T);

    doublereal presLow = 1.0E-2;
    doublereal oneBar = 1.0E5;
    doublereal dd = m_sub.density(T, presLow, WATER_GAS, 7.0E-8);
    setDensity(dd);
    setTemperature(T);
    SW_Offset = 0.0;
    doublereal s = entropy_mole();
    s -= GasConstant * log(oneBar/presLow);
    if (s != 188.835E3) {
        SW_Offset = 188.835E3 - s;
    }
    s = entropy_mole();
    s -= GasConstant * log(oneBar/presLow);

    doublereal h = enthalpy_mole();
    if (h != -241.826E6) {
        EW_Offset = -241.826E6 - h;
    }
    h = enthalpy_mole();

    /*
     * Set the initial state of the system to 298.15 K and
     * 1 bar.
     */
    setTemperature(298.15);
    double rho0 = m_sub.density(298.15, OneAtm, WATER_LIQUID);
    setDensity(rho0);

    m_waterProps.reset(new WaterProps(&m_sub));

    /*
     * We have to do something with the thermo function here.
     */
    delete m_spthermo;
    m_spthermo = 0;

    /*
     * Set the flag to say we are ready to calculate stuff
     */
    m_ready = true;
}