Пример #1
0
//! This utility routine decides whether a Cantera ThermoPhase needs
//! a constraint equation representing the charge neutrality of the
//! phase. It does this by searching for charged species. If it
//! finds one, and if the phase needs one, then it returns true.
static bool chargeNeutralityElement(const ThermoPhase* const tPhase)
{
    int hasCharge = hasChargedSpecies(tPhase);
    if (tPhase->chargeNeutralityNecessary() && hasCharge) {
        return true;
    }
    return false;
}
Пример #2
0
size_t vcs_VolPhase::transferElementsFM(const ThermoPhase* const tPhase)
{
    size_t nebase = tPhase->nElements();
    size_t ne = nebase;
    size_t ns = tPhase->nSpecies();

    /*
     * Decide whether we need an extra element constraint for charge
     * neutrality of the phase
     */
    bool cne = chargeNeutralityElement(tPhase);
    if (cne) {
        ChargeNeutralityElement = ne;
        ne++;
    }

    /*
     * Assign and malloc structures
     */
    elemResize(ne);


    if (ChargeNeutralityElement != npos) {
        m_elementType[ChargeNeutralityElement] = VCS_ELEM_TYPE_CHARGENEUTRALITY;
    }

    size_t eFound = npos;
    if (hasChargedSpecies(tPhase)) {
        if (cne) {
            /*
             * We need a charge neutrality constraint.
             * We also have an Electron Element. These are
             * duplicates of each other. To avoid trouble with
             * possible range error conflicts, sometimes we eliminate
             * the Electron condition. Flag that condition for elimination
             * by toggling the ElActive variable. If we find we need it
             * later, we will retoggle ElActive to true.
             */
            for (size_t eT = 0; eT < nebase; eT++) {
                if (tPhase->elementName(eT) == "E") {
                    eFound = eT;
                    m_elementActive[eT] = 0;
                    m_elementType[eT] = VCS_ELEM_TYPE_ELECTRONCHARGE;
                }
            }
        } else {
            for (size_t eT = 0; eT < nebase; eT++) {
                if (tPhase->elementName(eT) == "E") {
                    eFound = eT;
                    m_elementType[eT] = VCS_ELEM_TYPE_ELECTRONCHARGE;
                }
            }
        }
        if (eFound == npos) {
            eFound = ne;
            m_elementType[ne] = VCS_ELEM_TYPE_ELECTRONCHARGE;
            m_elementActive[ne] = 0;
            std::string ename = "E";
            m_elementNames[ne] = ename;
            ne++;
            elemResize(ne);
        }

    }

    m_formulaMatrix.resize(ns, ne, 0.0);

    m_speciesUnknownType.resize(ns, VCS_SPECIES_TYPE_MOLNUM);

    elemResize(ne);

    size_t e = 0;
    for (size_t eT = 0; eT < nebase; eT++) {
        m_elementNames[e] = tPhase->elementName(eT);
        m_elementType[e] = tPhase->elementType(eT);
        e++;
    }

    if (cne) {
        std::string pname = tPhase->id();
        if (pname == "") {
            std::stringstream sss;
            sss << "phase" << VP_ID_;
            pname = sss.str();
        }
        e = ChargeNeutralityElement;
        m_elementNames[e] = "cn_" + pname;
    }

    for (size_t k = 0; k < ns; k++) {
        e = 0;
        for (size_t eT = 0; eT < nebase; eT++) {
            m_formulaMatrix(k,e) = tPhase->nAtoms(k, eT);
            e++;
        }
        if (eFound != npos) {
            m_formulaMatrix(k,eFound) = - tPhase->charge(k);
        }
    }

    if (cne) {
        for (size_t k = 0; k < ns; k++) {
            m_formulaMatrix(k,ChargeNeutralityElement) = tPhase->charge(k);
        }
    }


    /*
     * Here, we figure out what is the species types are
     * The logic isn't set in stone, and is just for a particular type
     * of problem that I'm solving first.
     */
    if (ns == 1) {
        if (tPhase->charge(0) != 0.0) {
            m_speciesUnknownType[0] = VCS_SPECIES_TYPE_INTERFACIALVOLTAGE;
            setPhiVarIndex(0);
        }
    }

    return ne;
}