Exemple #1
0
  /*
   * 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);
#ifdef WITH_ELECTROLYTES
    if (model == "HMW") {
      HMWSoln* p = (HMWSoln*)t;
      p->constructPhaseXML(xmlphase,"");
    }
    else
#endif
      importPhase(xmlphase, t);
    return t;
  }
Exemple #2
0
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;
}
static void set_hmw_interactions(HMWSoln& p) {
    double beta0_nacl[] = {0.0765, 0.008946, -3.3158E-6, -777.03, -4.4706};
    double beta1_nacl[] = {0.2664, 6.1608E-5, 1.0715E-6, 0.0, 0.0};
    double beta2_nacl[] = {0.0, 0.0, 0.0, 0.0, 0.0};
    double cphi_nacl[] = {0.00127, -4.655E-5, 0.0, 33.317, 0.09421};
    p.setBinarySalt("Na+", "Cl-", 5, beta0_nacl, beta1_nacl, beta2_nacl,
        cphi_nacl, 2.0, 0.0);

    double beta0_hcl[] = {0.1775, 0.0, 0.0, 0.0, 0.0};
    double beta1_hcl[] = {0.2945, 0.0, 0.0, 0.0, 0.0};
    double beta2_hcl[] = {0.0, 0.0, 0.0, 0.0, 0.0};
    double cphi_hcl[] = {0.0008, 0.0, 0.0, 0.0, 0.0};
    p.setBinarySalt("H+", "Cl-", 5, beta0_hcl, beta1_hcl, beta2_hcl,
        cphi_hcl, 2.0, 0.0);

    double beta0_naoh[] = {0.0864, 0.0, 0.0, 0.0, 0.0};
    double beta1_naoh[] = {0.253, 0.0, 0.0, 0.0, 0.0};
    double beta2_naoh[] = {0.0, 0.0, 0.0, 0.0, 0.0};
    double cphi_naoh[] = {0.0044, 0.0, 0.0, 0.0, 0.0};
    p.setBinarySalt("Na+", "OH-", 5, beta0_naoh, beta1_naoh, beta2_naoh,
        cphi_naoh, 2.0, 0.0);

    double theta_cloh[] = {-0.05, 0.0, 0.0, 0.0, 0.0};
    double psi_nacloh[] = {-0.006, 0.0, 0.0, 0.0, 0.0};
    double theta_nah[] = {0.036, 0.0, 0.0, 0.0, 0.0};
    double psi_clnah[] = {-0.004, 0.0, 0.0, 0.0, 0.0};
    p.setTheta("Cl-", "OH-", 5, theta_cloh);
    p.setPsi("Na+", "Cl-", "OH-", 5, psi_nacloh);
    p.setTheta("Na+", "H+", 5, theta_nah);
    p.setPsi("Cl-", "Na+", "H+", 5, psi_clnah);
}
Exemple #4
0
  /*
   * 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;
  }
Exemple #5
0
int main(int argc, char** argv)
{

    int retn = 0;
    size_t i;

    try {
        std::string iFile = (argc > 1) ? argv[1] : "HMW_NaCl.xml";
        double V0[20], pmV[20];

        HMWSoln* HMW = new HMWSoln(iFile, "NaCl_electrolyte");


        /*
         * Load in and initialize the
         */
        Cantera::thermo_t* solid = newPhase<doublereal>("NaCl_Solid.xml","NaCl(S)");


        size_t nsp = HMW->nSpecies();
        //double acMol[100];
        //double act[100];
        double mf[100];
        double moll[100];
        HMW->getMoleFractions(mf);
        string sName;

        TemperatureTable TTable(15, false, 273.15, 25., 0, 0);


        HMW->setState_TP(298.15, 1.01325E5);

        size_t i1 = HMW->speciesIndex("Na+");
        size_t i2 = HMW->speciesIndex("Cl-");
        //int i3 = HMW->speciesIndex("H2O(L)");
        for (i = 0; i < nsp; i++) {
            moll[i] = 0.0;
        }
        HMW->setMolalities(moll);

        /*
         * Set the Pressure
         */
        double pres = OneAtm;

        /*
         * Fix the molality
         */
        double Is = 6.146;
        moll[i1] = Is;
        moll[i2] = Is;
        HMW->setState_TPM(298.15, pres, moll);
        double Xmol[30];
        HMW->getMoleFractions(Xmol);
        double meanMW = HMW->meanMolecularWeight();

        /*
         * ThermoUnknowns
         */
        double T;

        double V0_NaCl = 0.0, V0_Naplus = 0.0, V0_Clminus = 0.0, Delta_V0s = 0.0, V0_H2O = 0.0;
        double V_NaCl = 0.0, V_Naplus = 0.0, V_Clminus = 0.0, V_H2O = 0.0;
        double molarV0;
#ifdef DEBUG_HKM
        FILE* ttt = fopen("table.csv","w");
#endif
        printf("A_V   : Comparison to Pitzer's book, p. 99, can be made.\n");
        printf("        Agreement to 3  sig digits \n");
        printf("\n");

        printf("Delta_V0: Heat Capacity of Solution per mole of salt (standard states)\n");
        printf("           rxn for the ss heat of soln:     "
               "NaCl(s) -> Na+(aq) + Cl-(aq)\n");

        printf("\n");
        printf("Delta_Vs: Delta volume of Solution per mole of salt\n");
        printf("          rxn for heat of soln:     "
               " n1 H2O(l,pure) + n2 NaCl(s) -> n2 MX(aq) + n1 H2O(l) \n");
        printf("          Delta_Hs = (n1 h_H2O_bar + n2 h_MX_bar "
               "- n1 h_H2O_0 - n2 h_MX_0)/n2\n");
        printf("\n");
        printf("phiV:     phiV, calculated from the program, is checked\n");
        printf("          against analytical formula in V_standalone program.\n");
        printf("          (comparison against Pitzer book, p. 97, eqn. 96)\n");

        /*
         * Create a Table of NaCl Enthalpy Properties as a Function
         * of the Temperature
         */
        printf("\n\n");
        printf("            T,          Pres,         Aphi,            A_V,"
               "      Delta_V0,"
               "      Delta_Vs,           Vex,          phiV,"
               "        MolarV,     MolarV0\n");
        printf("       Kelvin,         bar, sqrt(kg/gmol),sqrt(kg/gmol)cm3/gmol,"
               "cm**3/gmolSalt,"
               "cm**3/gmolSalt,cm**3/gmolSoln,cm**3/gmolSalt,"
               "cm**3/gmol,   cm**3/gmol\n");
#ifdef DEBUG_HKM
        fprintf(ttt,"T, Pres, A_V, Vex, phiV, MolarV, MolarV0\n");
        fprintf(ttt,"Kelvin, bar, sqrt(kg/gmol)cm3/gmol, cm3/gmolSoln, cm3/gmolSalt, kJ/gmolSoln,"
                "kJ/gmolSoln\n");
#endif
        for (i = 0; i < TTable.NPoints + 1; i++) {
            if (i == TTable.NPoints) {
                T = 323.15;
            } else {
                T = TTable.T[i];
            }
            /*
             * RT is in units of J/kmolK
             */
            //double RT = GasConstant * T;

            /*
             * Make sure we are at the saturation pressure or above.
             */

            double psat = HMW->satPressure(T);

            pres = OneAtm;
            if (psat > pres) {
                pres = psat;
            }


            HMW->setState_TPM(T, pres, moll);

            solid->setState_TP(T, pres);

            /*
             * Get the Standard State volumes m3/kmol
             */
            solid->getStandardVolumes(V0);
            V0_NaCl = V0[0];
            HMW->getStandardVolumes(V0);
            V0_H2O     = V0[0];
            V0_Naplus  = V0[i1];
            V0_Clminus = V0[i2];

            /*
             * Calculate the standard state volume change of solution
             * for NaCl(s) -> Na+ + Cl-
             *   units: m3 / kmol
             */
            Delta_V0s = V0_Naplus + V0_Clminus - V0_NaCl;

            double dd = solid->density();
            double MW_NaCl = solid->meanMolecularWeight();
            V_NaCl = MW_NaCl / dd;
            //printf("V_NaCl = %g , V0_NaCl = %g %g\n", V_NaCl, V0_NaCl, 1.0/solid->molarDensity());

            /*
             * Get the partial molar volumes
             */
            HMW->getPartialMolarVolumes(pmV);
            V_H2O     = pmV[0];
            V_Naplus  = pmV[i1];
            V_Clminus = pmV[i2];


            //double Delta_V_Salt = V_NaCl - (V_Naplus + V_Clminus);

            /*
             * Calculate the molar volume of solution
             */
            double dsoln = HMW->density();
            meanMW = HMW->meanMolecularWeight();
            double molarV = meanMW / dsoln;
            //double md = HMW->molarDensity();
            //printf("compare %g %g\n", molarV, 1.0/md);

            /*
             * Calculate the delta volume of solution for the reaction
             *                NaCl(s) -> Na+ + Cl-
             */
            double Delta_Vs = (Xmol[0]  * V_H2O +
                               Xmol[i1] * V_Naplus +
                               Xmol[i2] * V_Clminus
                               - Xmol[0] * V0_H2O
                               - Xmol[i1] * V_NaCl);
            Delta_Vs /= Xmol[i1];


            /*
             * Calculate the apparent molar volume, J, from the
             * partial molar quantities, units m3/kmol
             */
            double Vex = (Xmol[0]  * (V_H2O    - V0_H2O) +
                          Xmol[i1] * (V_Naplus - V0_Naplus) +
                          Xmol[i2] * (V_Clminus - V0_Clminus));

            /*
             * Calculate the apparent relative molal volume, phiV,
             * units of m3/kmol
             */
            double phiV = Vex / Xmol[i1];

            double Aphi = HMW->A_Debye_TP(T, pres) / 3.0;
            //double AL = HMW->ADebye_L(T,pres);
            double Av = HMW->ADebye_V(T, pres) * 1.0E3;

            molarV0 = 0.0;
            for (size_t k = 0; k < nsp; k++) {
                molarV0 += Xmol[k] * V0[k];
            }

            if (i != TTable.NPoints+1) {
                printf("%13.4g, %13.4g, %13.4g, %13.4g, %13.4g, %13.4g, "
                       "%13.5g, %13.4g, %13.4g, %13.4g\n",
                       T, pres*1.0E-5,  Aphi, Av, Delta_V0s*1.0E3, Delta_Vs*1.0E3,
                       Vex*1.0E3, phiV*1.0E3, molarV*1.0E3 , molarV0*1.0E3);
#ifdef DEBUG_HKM
                fprintf(ttt,"%g, %g, %g, %g, %g, %g, %g\n",
                        T, pres*1.0E-5, Av, Vex*1.0E3, phiV*1.0E3, molarV*1.0E3 , molarV0*1.0E3);
#endif
            }

        }

        printf("Breakdown of Volume Calculation at 323.15 K, 1atm:\n");

        printf(" Species     MoleFrac        Molal          V0      "
               "    partV     (partV - V0)\n");
        printf("  H2O(L)");
        printf("%13.4g %13.4g %13.4g %13.4g %13.4g\n", Xmol[0], moll[0], V0_H2O*1.E3, V_H2O*1.E3,
               (V_H2O-V0_H2O)*1.E3);
        printf("  Na+   ");
        printf("%13.4g %13.4g %13.4g %13.4g %13.4g\n", Xmol[i1], moll[i1],
               V0_Naplus*1.E3 , V_Naplus*1.E3, (V_Naplus -V0_Naplus)*1.E3);
        printf("  Cl-   ");
        printf("%13.4g %13.4g %13.4g %13.4g %13.4g\n", Xmol[i2], moll[i2],
               V0_Clminus*1.E3, V_Clminus*1.E3, (V_Clminus - V0_Clminus)*1.E3);

        printf(" NaCl(s)");
        double dd = V_NaCl*1.E3 - V0_NaCl*1.E3;
        if (fabs(dd) < 1.0E-12) {
            dd = 0.0;
        }
        printf("%13.4g               %13.4g %13.4g %13.4g\n", 1.0,
               V0_NaCl*1.E3 , V_NaCl*1.E3,  dd);


        delete HMW;
        HMW = 0;
        delete solid;
        solid = 0;
        Cantera::appdelete();
#ifdef DEBUG_HKM
        fclose(ttt);
#endif
        return retn;

    } catch (CanteraError& err) {
        std::cout << err.what() << std::endl;
        Cantera::appdelete();
        return -1;
    }
}
Exemple #6
0
int main(int argc, char** argv)
{

    int retn = 0;
    size_t i;

    try {
        std::string iFile = (argc > 1) ? argv[1] : "HMW_NaCl.xml";
        double Cp0_R[20], pmCp[20];

        HMWSoln* HMW = new HMWSoln(iFile, "NaCl_electrolyte");


        /*
         * Load in and initialize the
         */
        Cantera::thermo_t* solid = newPhase<doublereal>("NaCl_Solid.xml","NaCl(S)");


        size_t nsp = HMW->nSpecies();
        double mf[100];
        double moll[100];
        for (i = 0; i < 100; i++) {
            mf[i] = 0.0;
        }

        HMW->getMoleFractions(mf);
        string sName;

        TemperatureTable TTable(15, false, 273.15, 25., 0, 0);


        HMW->setState_TP(298.15, 1.01325E5);

        size_t i1 = HMW->speciesIndex("Na+");
        size_t i2 = HMW->speciesIndex("Cl-");
        //int i3 = HMW->speciesIndex("H2O(L)");
        for (i = 0; i < nsp; i++) {
            moll[i] = 0.0;
        }
        HMW->setMolalities(moll);

        double Is = 0.0;

        /*
         * Set the Pressure
         */
        double pres = OneAtm;

        /*
         * Fix the molality
         */
        Is = 6.146;
        moll[i1] = Is;
        moll[i2] = Is;
        HMW->setState_TPM(298.15, pres, moll);
        double Xmol[30];
        HMW->getMoleFractions(Xmol);

        /*
         * ThermoUnknowns
         */
        double T;

        double Cp0_NaCl = 0.0, Cp0_Naplus = 0.0, Cp0_Clminus = 0.0, Delta_Cp0s = 0.0, Cp0_H2O = 0.0;
        double Cp_NaCl = 0.0, Cp_Naplus = 0.0, Cp_Clminus = 0.0, Cp_H2O = 0.0;
        double molarCp0;
#ifdef DEBUG_HKM
        FILE* ttt = fopen("table.csv","w");
#endif
        printf("A_J/R: Comparison to Pitzer's book, p. 99, can be made.\n");
        printf("        Agreement is within 12 pc \n");
        printf("\n");

        printf("Delta_Cp0: Heat Capacity of Solution per mole of salt (standard states)\n");
        printf("           rxn for the ss heat of soln:     "
               "NaCl(s) -> Na+(aq) + Cl-(aq)\n");

        printf("\n");
        printf("Delta_Cps: Delta heat Capacity of Solution per mole of salt\n");
        printf("          rxn for heat of soln:     "
               " n1 H2O(l,pure) + n2 NaCl(s) -> n2 MX(aq) + n1 H2O(l) \n");
        printf("          Delta_Hs = (n1 h_H2O_bar + n2 h_MX_bar "
               "- n1 h_H2O_0 - n2 h_MX_0)/n2\n");
        printf("\n");
        printf("phiJ:     phiJ, calculated from the program, is checked\n");
        printf("          against analytical formula in J_standalone program.\n");
        printf("          (comparison against Eq. 12, Silvester and Pitzer)\n");

        /*
         * Create a Table of NaCl Enthalpy Properties as a Function
         * of the Temperature
         */
        printf("\n\n");
        printf("            T,          Pres,          Aphi,         A_J/R,"
               "     Delta_Cp0,"
               "     Delta_Cps,             J,          phiJ,"
               "     MolarCp,   MolarCp0\n");
        printf("       Kelvin,           bar, sqrt(kg/gmol), sqrt(kg/gmol),"
               "   kJ/gmolSalt,"
               "   kJ/gmolSalt,   kJ/gmolSoln,   kJ/gmolSalt,"
               "       kJ/gmol,    kJ/gmol\n");
#ifdef DEBUG_HKM
        fprintf(ttt,"T, Pres, A_J/R, Delta_Cp0, Delta_Cps, J, phiJ\n");
        fprintf(ttt,"Kelvin, bar, sqrt(kg/gmol), kJ/gmolSalt, kJ/gmolSalt, kJ/gmolSoln,"
                "kJ/gmolSalt\n");
#endif
        for (i = 0; i < TTable.NPoints + 1; i++) {
            if (i == TTable.NPoints) {
                T = 323.15;
            } else {
                T = TTable.T[i];
            }
            /*
             * RT is in units of J/kmolK
             */
            //double RT = GasConstant * T;

            /*
             * Make sure we are at the saturation pressure or above.
             */

            double psat = HMW->satPressure(T);

            pres = OneAtm;
            if (psat > pres) {
                pres = psat;
            }


            HMW->setState_TPM(T, pres, moll);

            solid->setState_TP(T, pres);

            /*
             * Get the Standard State DeltaH
             */

            solid->getCp_R(Cp0_R);
            Cp0_NaCl = Cp0_R[0] * GasConstant * 1.0E-6;


            HMW->getCp_R(Cp0_R);
            Cp0_H2O    = Cp0_R[0] * GasConstant * 1.0E-6;
            Cp0_Naplus = Cp0_R[i1] * GasConstant * 1.0E-6;
            Cp0_Clminus = Cp0_R[i2] * GasConstant * 1.0E-6;
            /*
             * Calculate the standard state heat of solution
             * for NaCl(s) -> Na+ + Cl-
             *   units: kJ/gmolSalt
             */

            Delta_Cp0s = Cp0_Naplus + Cp0_Clminus - Cp0_NaCl;

            pmCp[0] = solid->cp_mole();

            Cp_NaCl = pmCp[0] * 1.0E-6;


            HMW->getPartialMolarCp(pmCp);
            Cp_H2O     = pmCp[0]  * 1.0E-6;
            Cp_Naplus  = pmCp[i1] * 1.0E-6;
            Cp_Clminus = pmCp[i2] * 1.0E-6;

            //double Delta_Cp_Salt = Cp_NaCl - (Cp_Naplus + Cp_Clminus);

            double molarCp = HMW->cp_mole() * 1.0E-6;

            /*
             * Calculate the heat capacity of solution for the reaction
             * NaCl(s) -> Na+ + Cl-
             */
            double Delta_Cps = (Xmol[0]  * Cp_H2O +
                                Xmol[i1] * Cp_Naplus +
                                Xmol[i2] * Cp_Clminus
                                - Xmol[0] * Cp0_H2O
                                - Xmol[i1] * Cp_NaCl);
            Delta_Cps /= Xmol[i1];


            /*
             * Calculate the relative heat capacity, J, from the
             * partial molar quantities, units J/gmolSolutionK
             */
            double J = (Xmol[0]  * (Cp_H2O    - Cp0_H2O) +
                        Xmol[i1] * (Cp_Naplus - Cp0_Naplus) +
                        Xmol[i2] * (Cp_Clminus - Cp0_Clminus));

            /*
             * Calculate the apparent relative molal heat capacity, phiJ,
             * units of J/gmolSaltAddedK
             */
            double phiJ = J / Xmol[i1];


            double Aphi = HMW->A_Debye_TP(T, pres) / 3.0;
            //double AL = HMW->ADebye_L(T,pres);
            double AJ = HMW->ADebye_J(T, pres);

            for (size_t k = 0; k < nsp; k++) {
                Cp0_R[k] *= GasConstant * 1.0E-6;
            }

            molarCp0 = 0.0;
            for (size_t k = 0; k < nsp; k++) {
                molarCp0 += Xmol[k] * Cp0_R[k];
            }

            if (i != TTable.NPoints+1) {
                printf("%13.5g, %13.5g, %13.5g, %13.5g, %13.5g, %13.5g, "
                       "%13.5g, %13.5g, %13.5g, %13.5g\n",
                       T, pres*1.0E-5,  Aphi, AJ/GasConstant, Delta_Cp0s, Delta_Cps,
                       J, phiJ, molarCp , molarCp0);
#ifdef DEBUG_HKM
                fprintf(ttt,"%g, %g, %g, %g, %g, %g, %g\n",
                        T, pres*1.0E-5, AJ/GasConstant, Delta_Cp0s, Delta_Cps, J, phiJ);
#endif
            }

        }

        printf("Breakdown of Heat Capacity Calculation at 323.15 K, 1atm:\n");

        printf(" Species     MoleFrac        Molal          Cp0      "
               "    partCp     (partCp - Cp0)\n");
        printf("  H2O(L)");
        printf("%13.5g %13.5g %13.5g %13.5g %13.5g\n", Xmol[0], moll[0], Cp0_H2O , Cp_H2O,  Cp_H2O-Cp0_H2O);
        printf("  Na+   ");
        printf("%13.5g %13.5g %13.5g %13.5g %13.5g\n", Xmol[i1], moll[i1],
               Cp0_Naplus , Cp_Naplus,  Cp_Naplus -Cp0_Naplus);
        printf("  Cl-   ");
        printf("%13.5g %13.5g %13.5g %13.5g %13.5g\n", Xmol[i2], moll[i2],
               Cp0_Clminus , Cp_Clminus,  Cp_Clminus - Cp0_Clminus);

        printf(" NaCl(s)");
        printf("%13.5g               %13.5g %13.5g %13.5g\n", 1.0,
               Cp0_NaCl , Cp_NaCl,  Cp_NaCl - Cp0_NaCl);


        delete HMW;
        HMW = 0;
        delete solid;
        solid = 0;
        Cantera::appdelete();

#ifdef DEBUG_HKM
        fclose(ttt);
#endif
        return retn;

    } catch (CanteraError& err) {
        std::cout << err.what() << std::endl;
        Cantera::appdelete();
        return -1;
    }
}
Exemple #7
0
int main(int argc, char **argv)
{
#ifdef _MSC_VER
    _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
   int retn = 0;

   try {
  
     HMWSoln *HMW = new HMWSoln(1);

#ifdef DEBUG_MODE
     CHECK_DEBUG_MODE = 1;
#endif
     if (CHECK_DEBUG_MODE == 1) {
       HMW->m_debugCalc = 1;
       if (HMW->debugPrinting()) {
         FILE *ff = fopen("CheckDebug.txt", "w");
         fprintf(ff,"%1d\n", 1);
         fclose(ff);
       }
       HMW->m_debugCalc = 0;
     }
     
     int nsp = HMW->nSpecies();
    
     double a1 = HMW->AionicRadius(1);
     printf("a1 = %g\n", a1);
     double a2 = HMW->AionicRadius(2);
     printf("a2 = %g\n", a2); 
     double mu0[100];
     double moll[100]; 
     string sName;
  
     HMW->getMolalities(moll);
     moll[1] = 6.0997;
     moll[2] = 2.1628E-9;
     moll[3] = 6.0997;
     moll[4] =1.3977E-6;
     /*
      * Equalize charge balance and dump into Cl-
      */
     double sum = -moll[1] + moll[2] + moll[3] - moll[4];
     moll[1] += sum;

     HMW->setMolalities(moll);
     HMW->setState_TP(298.15, 1.01325E5);
     pAtable(HMW);

     HMW->setState_TP(298.15, 1.01325E5);
     HMW->getStandardChemPotentials(mu0);
     // translate from J/kmol to kJ/gmol
     int k;
     for (k = 0; k < nsp; k++) {
        mu0[k] *= 1.0E-6; 
     }

     printf("           Species   Standard chemical potentials (kJ/gmol) \n");
     printf("------------------------------------------------------------\n");
     for (k = 0; k < nsp; k++) {
       sName = HMW->speciesName(k);
       printf("%16s %16.9g\n", sName.c_str(), mu0[k]);
     }
     printf("------------------------------------------------------------\n");
     printf(" Some DeltaSS values:               Delta(mu_0)\n");
     double deltaG;
     int i1, i2, j1;
     double RT = 8.314472E-3 * 298.15;

 
     
   
 
     i1 = HMW->speciesIndex("Na+");
     i2 = HMW->speciesIndex("Cl-");
     deltaG = -432.6304 - mu0[i1] - mu0[i2];
     printf(" NaCl(S): Na+ + Cl- -> NaCl(S): %14.7g kJ/gmol \n",
            deltaG);
     printf("                                : %14.7g (dimensionless) \n",
            deltaG/RT);
     printf("                                : %14.7g (dimensionless/ln10) \n",
            deltaG/(RT * log(10.0)));
     printf("            G0(NaCl(S)) = %14.7g (fixed)\n", -432.6304);
     printf("            G0(Na+)     = %14.7g\n", mu0[i1]);
     printf("            G0(Cl-)     = %14.7g\n", mu0[i2]);

     i1 = HMW->speciesIndex("H+");
     i2 = HMW->speciesIndex("H2O(L)");
     j1 = HMW->speciesIndex("OH-");
     if (i1 < 0 || i2 < 0 || j1 < 0) {
       printf("problems\n");
       exit(-1);
     }
     deltaG = mu0[j1] + mu0[i1] - mu0[i2];
     printf(" OH-: H2O(L) - H+ -> OH-: %14.7g kJ/gmol \n",
            deltaG);
     printf("                                : %14.7g (dimensionless) \n",
            deltaG/RT);
     printf("                                : %14.7g (dimensionless/ln10) \n",
            deltaG/(RT * log(10.0)));
     printf("            G0(OH-)    = %14.7g\n", mu0[j1]);
     printf("            G0(H+)     = %14.7g\n", mu0[i1]);
     printf("            G0(H2O(L)) = %14.7g\n", mu0[i2]);


     printf("------------------------------------------------------------\n");

     delete HMW;
     HMW = 0;
     Cantera::appdelete();

     return retn;

   } catch (CanteraError) {

     showErrors();
     return -1;
   }
} 
int main(int argc, char** argv)
{
#if defined(_MSC_VER) && _MSC_VER < 1900
    _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
    int retn = 0;

    try {

        HMWSoln* HMW = new HMWSoln("HMW_NaCl.xml");
        HMW->printCoeffs();

        size_t nsp = HMW->nSpecies();

        double a1 = HMW->AionicRadius(1);
        printf("a1 = %g\n", a1);
        double a2 = HMW->AionicRadius(2);
        printf("a2 = %g\n", a2);
        double mu0[100];
        double moll[100];
        string sName;

        HMW->getMolalities(moll);
        moll[1] = 6.0997;
        moll[2] = 2.1628E-9;
        moll[3] = 6.0997;
        moll[4] =1.3977E-6;
        /*
         * Equalize charge balance and dump into Cl-
         */
        double sum = -moll[1] + moll[2] + moll[3] - moll[4];
        moll[1] += sum;

        HMW->setMolalities(moll);
        HMW->setState_TP(298.15, 1.01325E5);
        pAtable(HMW);

        HMW->setState_TP(298.15, 1.01325E5);
        HMW->getStandardChemPotentials(mu0);
        // translate from J/kmol to kJ/gmol
        for (size_t k = 0; k < nsp; k++) {
            mu0[k] *= 1.0E-6;
        }

        printf("           Species   Standard chemical potentials (kJ/gmol) \n");
        printf("------------------------------------------------------------\n");
        for (size_t k = 0; k < nsp; k++) {
            sName = HMW->speciesName(k);
            printf("%16s %16.9g\n", sName.c_str(), mu0[k]);
        }
        printf("------------------------------------------------------------\n");
        printf(" Some DeltaSS values:               Delta(mu_0)\n");
        double deltaG;
        size_t i1, i2, j1;
        double RT = 8.314472E-3 * 298.15;

        i1 = HMW->speciesIndex("Na+");
        i2 = HMW->speciesIndex("Cl-");
        deltaG = -432.6304 - mu0[i1] - mu0[i2];
        printf(" NaCl(S): Na+ + Cl- -> NaCl(S): %14.7g kJ/gmol \n",
               deltaG);
        printf("                                : %14.7g (dimensionless) \n",
               deltaG/RT);
        printf("                                : %14.7g (dimensionless/ln10) \n",
               deltaG/(RT * log(10.0)));
        printf("            G0(NaCl(S)) = %14.7g (fixed)\n", -432.6304);
        printf("            G0(Na+)     = %14.7g\n", mu0[i1]);
        printf("            G0(Cl-)     = %14.7g\n", mu0[i2]);

        i1 = HMW->speciesIndex("H+");
        i2 = HMW->speciesIndex("H2O(L)");
        j1 = HMW->speciesIndex("OH-");
        if (i1 == npos || i2 == npos || j1 == npos) {
            printf("problems\n");
            exit(-1);
        }
        deltaG = mu0[j1] + mu0[i1] - mu0[i2];
        printf(" OH-: H2O(L) - H+ -> OH-: %14.7g kJ/gmol \n",
               deltaG);
        printf("                                : %14.7g (dimensionless) \n",
               deltaG/RT);
        printf("                                : %14.7g (dimensionless/ln10) \n",
               deltaG/(RT * log(10.0)));
        printf("            G0(OH-)    = %14.7g\n", mu0[j1]);
        printf("            G0(H+)     = %14.7g\n", mu0[i1]);
        printf("            G0(H2O(L)) = %14.7g\n", mu0[i2]);


        printf("------------------------------------------------------------\n");

        delete HMW;
        HMW = 0;
        Cantera::appdelete();

        return retn;

    } catch (CanteraError& err) {
        std::cout << err.what() << std::endl;
        return -1;
    }
}
TEST(HMWSoln, fromScratch_HKFT)
{
    HMWSoln p;
    auto sH2O = make_species("H2O(l)", "H:2, O:1", h2oliq_nasa_coeffs);
    auto sNa = make_species("Na+", "Na:1, E:-1", 0.0,
                            298.15, -125.5213, 333.15, -125.5213, 1e5);
    sNa->charge = 1;
    auto sCl = make_species("Cl-", "Cl:1, E:1", 0.0,
                            298.15, -52.8716, 333.15, -52.8716, 1e5);
    sCl->charge = -1;
    auto sH = make_species("H+", "H:1, E:-1", 0.0, 298.15, 0.0, 333.15, 0.0, 1e5);
    sH->charge = 1;
    auto sOH = make_species("OH-", "O:1, H:1, E:1", 0.0,
                            298.15, -91.523, 333.15, -91.523, 1e5);
    sOH->charge = -1;
    for (auto& s : {sH2O, sNa, sCl, sH, sOH}) {
        p.addSpecies(s);
    }
    double h0[] = {-57433, Undef, 0.0, -54977};
    double g0[] = {Undef, -31379, 0.0, -37595};
    double s0[] = {13.96, 13.56, Undef, -2.56};
    double a[][4] = {{0.1839, -228.5, 3.256, -27260},
                     {0.4032, 480.1, 5.563, -28470},
                     {0.0, 0.0, 0.0, 0.0},
                     {0.12527, 7.38, 1.8423, -27821}};
    double c[][2] = {{18.18, -29810}, {-4.4, -57140}, {0.0, 0.0}, {4.15, -103460}};
    double omega[] = {33060, 145600, 0.0, 172460};

    std::unique_ptr<PDSS_Water> ss(new PDSS_Water());
    p.installPDSS(0, std::move(ss));
    for (size_t k = 0; k < 4; k++) {
        std::unique_ptr<PDSS_HKFT> ss(new PDSS_HKFT());
        if (h0[k] != Undef) {
            ss->setDeltaH0(h0[k] * toSI("cal/gmol"));
        }
        if (g0[k] != Undef) {
            ss->setDeltaG0(g0[k] * toSI("cal/gmol"));
        }
        if (s0[k] != Undef) {
            ss->setS0(s0[k] * toSI("cal/gmol/K"));
        }
        a[k][0] *= toSI("cal/gmol/bar");
        a[k][1] *= toSI("cal/gmol");
        a[k][2] *= toSI("cal-K/gmol/bar");
        a[k][3] *= toSI("cal-K/gmol");
        c[k][0] *= toSI("cal/gmol/K");
        c[k][1] *= toSI("cal-K/gmol");
        ss->set_a(a[k]);
        ss->set_c(c[k]);
        ss->setOmega(omega[k] * toSI("cal/gmol"));
        p.installPDSS(k+1, std::move(ss));
    }
    p.setPitzerTempModel("complex");
    p.setA_Debye(-1);
    p.initThermo();

    set_hmw_interactions(p);
    p.setMolalitiesByName("Na+:6.0954 Cl-:6.0954 H+:2.1628E-9 OH-:1.3977E-6");
    p.setState_TP(50 + 273.15, 101325);

    size_t N = p.nSpecies();
    vector_fp mv(N), h(N), mu(N), ac(N), acoeff(N);
    p.getPartialMolarVolumes(mv.data());
    p.getPartialMolarEnthalpies(h.data());
    p.getChemPotentials(mu.data());
    p.getActivities(ac.data());
    p.getActivityCoefficients(acoeff.data());

    double mvRef[] = {0.01815224, 0.00157182, 0.01954605, 0.00173137, -0.0020266};

    for (size_t k = 0; k < N; k++) {
        EXPECT_NEAR(mv[k], mvRef[k], 2e-8);
    }
}
TEST(HMWSoln, fromScratch)
{
    // Regression test based on HMW_test_3
    HMWSoln p;
    auto sH2O = make_species("H2O(l)", "H:2, O:1", h2oliq_nasa_coeffs);
    auto sCl = make_species("Cl-", "Cl:1, E:1", 0.0,
                            298.15, -52.8716, 333.15, -52.8716, 1e5);
    sCl->charge = -1;
    auto sH = make_species("H+", "H:1, E:-1", 0.0, 298.15, 0.0, 333.15, 0.0, 1e5);
    sH->charge = 1;
    auto sNa = make_species("Na+", "Na:1, E:-1", 0.0,
                            298.15, -125.5213, 333.15, -125.5213, 1e5);
    sNa->charge = 1;
    auto sOH = make_species("OH-", "O:1, H:1, E:1", 0.0,
                            298.15, -91.523, 333.15, -91.523, 1e5);
    sOH->charge = -1;
    for (auto& s : {sH2O, sCl, sH, sNa, sOH}) {
        p.addSpecies(s);
    }
    std::unique_ptr<PDSS_Water> ss(new PDSS_Water());
    p.installPDSS(0, std::move(ss));
    size_t k = 1;
    for (double v : {1.3, 1.3, 1.3, 1.3}) {
        std::unique_ptr<PDSS_ConstVol> ss(new PDSS_ConstVol());
        ss->setMolarVolume(v);
        p.installPDSS(k++, std::move(ss));
    }
    p.setPitzerTempModel("complex");
    p.setA_Debye(1.175930);
    p.initThermo();

    set_hmw_interactions(p);
    p.setMolalitiesByName("Na+:6.0997 Cl-:6.0996986044628 H+:2.1628E-9 OH-:1.3977E-6");
    p.setState_TP(150 + 273.15, 101325);

    size_t N = p.nSpecies();
    vector_fp acMol(N), mf(N), activities(N), moll(N), mu0(N);
    p.getMolalityActivityCoefficients(acMol.data());
    p.getMoleFractions(mf.data());
    p.getActivities(activities.data());
    p.getMolalities(moll.data());
    p.getStandardChemPotentials(mu0.data());

    double acMolRef[] = {0.9341, 1.0191, 3.9637, 1.0191, 0.4660};
    double mfRef[] = {0.8198, 0.0901, 0.0000, 0.0901, 0.0000};
    double activitiesRef[] = {0.7658, 6.2164, 0.0000, 6.2164, 0.0000};
    double mollRef[] = {55.5084, 6.0997, 0.0000, 6.0997, 0.0000};
    double mu0Ref[] = {-317.175788, -186.014558, 0.0017225, -441.615429, -322.000412}; // kJ/gmol

    for (size_t k = 0 ; k < N; k++) {
        EXPECT_NEAR(acMol[k], acMolRef[k], 2e-4);
        EXPECT_NEAR(mf[k], mfRef[k], 2e-4);
        EXPECT_NEAR(activities[k], activitiesRef[k], 2e-4);
        EXPECT_NEAR(moll[k], mollRef[k], 2e-4);
        EXPECT_NEAR(mu0[k]/1e6, mu0Ref[k], 2e-6);
    }
}
Exemple #11
0
int main(int argc, char** argv)
{

    int retn = 0;
    size_t i;
    string commandFile;
    try {

        char iFile[80];
        strcpy(iFile, "HMW_NaCl.xml");
        if (argc > 1) {
            strcpy(iFile, argv[1]);
        }
        double Temp = 273.15 + 275.;

        double aTemp[7];
        aTemp[0] = 298.15;
        aTemp[1] = 273.15 + 100.;
        aTemp[2] = 273.15 + 150.;
        aTemp[3] = 273.15 + 200.;
        aTemp[4] = 273.15 + 250.;
        aTemp[5] = 273.15 + 275.;
        aTemp[6] = 273.15 + 300.;

        HMWSoln* HMW = new HMWSoln(iFile, "NaCl_electrolyte");

        size_t nsp = HMW->nSpecies();
        double acMol[100];
        double act[100];
        double mf[100];
        double moll[100];

        for (i = 0; i < 100; i++) {
            acMol[i] = 1.0;
            act[i] = 1.0;
            mf[i] = 0.0;
            moll[i] = 0.0;
        }

        HMW->getMoleFractions(mf);
        string sName;
        FILE* ff;
        char fname[64];

        for (int jTemp = 0; jTemp < 7; jTemp++) {
            Temp = aTemp[jTemp];
            sprintf(fname, "T%3.0f.csv", Temp);

            ff = fopen(fname, "w");
            HMW->setState_TP(Temp, 1.01325E5);
            printf("   Temperature = %g K\n", Temp);
            size_t i1 = HMW->speciesIndex("Na+");
            size_t i2 = HMW->speciesIndex("Cl-");
            size_t i3 = HMW->speciesIndex("H2O(L)");
            for (i = 1; i < nsp; i++) {
                moll[i] = 0.0;
            }
            HMW->setState_TPM(Temp, OneAtm, moll);
            double Itop = 10.;
            double Ibot = 0.0;
            double ISQRTtop = sqrt(Itop);
            double ISQRTbot = sqrt(Ibot);
            double ISQRT;
            double Is = 0.0;
            size_t its = 100;
            bool doneSp = false;
            fprintf(ff,"              Is,     sqrtIs,     meanAc,"
                    "  log10(meanAC),     acMol_Na+,"
                    "     acMol_Cl-,   ac_Water, act_Water, OsmoticCoeff\n");
            for (i = 0; i < its; i++) {
                ISQRT = ISQRTtop*((double)i)/(its - 1.0)
                        + ISQRTbot*(1.0 - (double)i/(its - 1.0));

                Is = ISQRT * ISQRT;
                if (!doneSp) {
                    if (Is > 6.146) {
                        Is = 6.146;
                        doneSp = true;
                        i = i - 1;
                    }
                }
                moll[i1] = Is;
                moll[i2] = Is;
                HMW->setMolalities(moll);
                HMW->getMolalityActivityCoefficients(acMol);
                HMW->getActivities(act);
                double oc = HMW->osmoticCoefficient();
                double meanAC = sqrt(acMol[i1] * acMol[i2]);
                fprintf(ff,"%15g, %15g, %15g, %15g, %15g, %15g, %15g, %15g, %15g\n",
                        Is, ISQRT, meanAC, log10(meanAC),
                        acMol[i1], acMol[i2], acMol[i3], act[i3], oc);
            }
            fclose(ff);
        }


        delete HMW;
        HMW = 0;
        Cantera::appdelete();

        return retn;

    } catch (CanteraError& err) {
        std::cout << err.what() << std::endl;
        return -1;
    }
}