*** empty log message ***
This commit is contained in:
parent
916c065a9f
commit
76526a6aa3
41 changed files with 2086 additions and 163 deletions
|
|
@ -728,6 +728,10 @@ extern "C" {
|
|||
catch (CanteraError) { return -1; }
|
||||
}
|
||||
|
||||
int DLL_EXPORT trans_setParameters(int n, int type, int k, double* d) {
|
||||
try { trans(n)->setParameters(type, k, d); return 0;}
|
||||
catch (CanteraError) { return -1; }
|
||||
}
|
||||
|
||||
//-------------------- Functions ---------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ extern "C" {
|
|||
int DLL_IMPORT trans_getMixDiffCoeffs(int n, int ld, double* d);
|
||||
int DLL_IMPORT trans_getBinDiffCoeffs(int n, int ld, double* d);
|
||||
int DLL_IMPORT trans_getMultiDiffCoeffs(int n, int ld, double* d);
|
||||
int DLL_IMPORT trans_setParameters(int n, int type, int k, double* d);
|
||||
|
||||
int DLL_IMPORT import_phase(int nth, int nxml, char* id);
|
||||
int DLL_IMPORT import_kinetics(int nxml, char* id,
|
||||
|
|
|
|||
5
Cantera/matlab/cantera/@Transport/setParameters.m
Normal file
5
Cantera/matlab/cantera/@Transport/setParameters.m
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
function setParameters(tr, type, k, p)
|
||||
% SETPARAMETERS - set parameters.
|
||||
%
|
||||
v = trans_get(tr.id, 31, type, k, p);
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
function setThermalConductivity(tr, lam)
|
||||
% SETTHERMALCONDUCTIVITY - Set the thermal conductivity.
|
||||
%
|
||||
% This method can only be used with transport models that
|
||||
% support directly setting the value of the thermal
|
||||
% conductivity.
|
||||
%
|
||||
setParameters(tr, 1, 0, lam);
|
||||
|
||||
|
|
@ -10,8 +10,8 @@ t0 = cputime; % record the starting time
|
|||
% parameter values
|
||||
p = oneatm; % pressure
|
||||
tin = 300.0; % inlet temperature
|
||||
mdot_o = 0.24; % air, kg/m^2/s
|
||||
mdot_f = 0.08; % fuel, kg/m^2/s
|
||||
mdot_o = 0.72; % air, kg/m^2/s
|
||||
mdot_f = 0.24; % fuel, kg/m^2/s
|
||||
|
||||
rxnmech = 'gri30.xml'; % reaction mechanism file
|
||||
transport = 'Mix'; % transport model
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ void reportError();
|
|||
mexErrMsgTxt("unknown Transport method");
|
||||
}
|
||||
}
|
||||
|
||||
else if (job < 30) {
|
||||
nsp = getInt(prhs[3]);
|
||||
plhs[0] = mxCreateNumericMatrix(nsp,nsp,mxDOUBLE_CLASS,mxREAL);
|
||||
|
|
@ -80,6 +81,25 @@ void reportError();
|
|||
mexErrMsgTxt("unknown Transport method");
|
||||
}
|
||||
}
|
||||
|
||||
// set parameters
|
||||
else if (job < 40) {
|
||||
double* params;
|
||||
int typ, k;
|
||||
switch (job) {
|
||||
case 31:
|
||||
typ = getInt(prhs[3]);
|
||||
k = getInt(prhs[4]);
|
||||
params = mxGetPr(prhs[5]);
|
||||
iok = trans_setParameters(n, typ, k, params);
|
||||
break;
|
||||
default:
|
||||
mexErrMsgTxt("unknown Transport method");
|
||||
}
|
||||
plhs[0] = mxCreateNumericMatrix(1,1,mxDOUBLE_CLASS,mxREAL);
|
||||
h = mxGetPr(plhs[0]);
|
||||
*h = double(iok);
|
||||
}
|
||||
else {
|
||||
mexErrMsgTxt("unknown Transport method");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -404,7 +404,6 @@ class OneDim:
|
|||
"""
|
||||
|
||||
self.setNewtonOptions(max_jac_age = self._opt['ts_jac_age'])
|
||||
print 'max jac age = ',self._opt['ts_jac_age']
|
||||
|
||||
if loglevel > 0:
|
||||
print_heading('Begin time integration.\n\n')
|
||||
|
|
|
|||
34
Cantera/python/Cantera/SolidTransport.py
Normal file
34
Cantera/python/Cantera/SolidTransport.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
"""
|
||||
Transport properties for solids.
|
||||
|
||||
This class implements a simple model for the diffusion coefficients and
|
||||
the thermal conductivity of a solid. The diffusion coefficients have
|
||||
modified Arrhenius form, and the thermal conductivity is constant.
|
||||
All parameters are user-specified, not computed from a physical model.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> tr = SolidTransport(solid_phase)
|
||||
>>> tr.setThermalConductivity(0.5) # W/m/K
|
||||
>>> tr.setDiffCoeff(species = "OxygenIon", A = 2.0, n = 0.0, E = 700.0)
|
||||
|
||||
Note that the diffusion coefficient is computed from D = A * T^n *
|
||||
exp(-E/t) in m^2/s. Diffusion coefficients for unspecified species are
|
||||
set to zero.
|
||||
|
||||
"""
|
||||
|
||||
from Cantera.Transport import Transport
|
||||
|
||||
class SolidTransport(Transport):
|
||||
def __init__(self, phase = None):
|
||||
Transport.__init__(self, model = "Solid", phase = phase)
|
||||
|
||||
def setThermalConductivity(self, lamb):
|
||||
self.setParameters(1, 0, [lamb, 0.0])
|
||||
|
||||
def setDiffCoeff(self, species = "", A = 0.0, n = 0.0, E = 0.0):
|
||||
k = self._phase.speciesIndex(species)
|
||||
self.setParameters(0, k, [A, n, E])
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import _cantera
|
||||
from Numeric import asarray
|
||||
|
||||
class Transport:
|
||||
|
||||
|
|
@ -80,5 +81,10 @@ class Transport:
|
|||
|
||||
def multiDiffCoeffs(self):
|
||||
return _cantera.tran_multiDiffCoeffs(self.__tr_id,
|
||||
self.trnsp)
|
||||
self.trnsp)
|
||||
|
||||
def setParameters(self, type, k, params):
|
||||
return _cantera.tran_setParameters(self.__tr_id,
|
||||
type, k, asarray(params))
|
||||
|
||||
|
||||
|
|
|
|||
46
Cantera/python/Cantera/solid.py
Normal file
46
Cantera/python/Cantera/solid.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"""
|
||||
"""
|
||||
|
||||
import string
|
||||
import os
|
||||
|
||||
from constants import *
|
||||
from ThermoPhase import ThermoPhase
|
||||
from Kinetics import Kinetics
|
||||
from SolidTransport import SolidTransport
|
||||
import XML
|
||||
import _cantera
|
||||
|
||||
class Solid(ThermoPhase, Kinetics, SolidTransport):
|
||||
"""
|
||||
"""
|
||||
|
||||
def __init__(self, src="", root=None):
|
||||
|
||||
self.ckin = 0
|
||||
self._owner = 0
|
||||
self.verbose = 1
|
||||
|
||||
# get the 'phase' element
|
||||
s = XML.find_XML(src=src, root=root, name="phase")
|
||||
|
||||
# get the equation of state model
|
||||
ThermoPhase.__init__(self, xml_phase=s)
|
||||
|
||||
# get the kinetics model
|
||||
Kinetics.__init__(self, xml_phase=s, phases=[self])
|
||||
|
||||
SolidTransport.__init__(self, phase=self)
|
||||
|
||||
#self.setState_TP(300.0, OneAtm)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return _cantera.phase_report(self._phase_id, self.verbose)
|
||||
|
||||
|
||||
def __del__(self):
|
||||
SolidTransport.__del__(self)
|
||||
Kinetics.__del__(self)
|
||||
ThermoPhase.__del__(self)
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from solution import Solution
|
||||
|
||||
def Solid(import_file="", id="",
|
||||
def Solid(src="",
|
||||
kmodel=1, transport=None):
|
||||
return Solution(import_file=import_file,
|
||||
thermo_db="",
|
||||
|
|
|
|||
|
|
@ -30,6 +30,21 @@ py_transport_delete(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
py_setParameters(PyObject *self, PyObject *args) {
|
||||
int n, k, typ;
|
||||
PyObject* parray;
|
||||
if (!PyArg_ParseTuple(args, "iiiO:py_setParameters",
|
||||
&n, &typ, &k, &parray)) return NULL;
|
||||
|
||||
PyArrayObject* a = (PyArrayObject*)parray;
|
||||
double* xd = (double*)a->data;
|
||||
int ok = trans_setParameters(n, typ, k, xd);
|
||||
if (ok < 0) return reportError(ok);
|
||||
return Py_BuildValue("i",ok);
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
py_viscosity(PyObject *self, PyObject *args) {
|
||||
int n;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ static PyMethodDef ct_methods[] = {
|
|||
{"tran_binaryDiffCoeffs", py_binaryDiffCoeffs, METH_VARARGS},
|
||||
{"tran_mixDiffCoeffs", py_mixDiffCoeffs, METH_VARARGS},
|
||||
{"tran_multiDiffCoeffs", py_multiDiffCoeffs, METH_VARARGS},
|
||||
{"tran_setParameters", py_setParameters, METH_VARARGS},
|
||||
|
||||
{"get_Cantera_Error", ct_get_cantera_error, METH_VARARGS},
|
||||
{"ct_print", ct_print, METH_VARARGS},
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
namespace Cantera {
|
||||
|
||||
ImplicitSurfChem::ImplicitSurfChem(SurfKinetics& kin)
|
||||
ImplicitSurfChem::ImplicitSurfChem(InterfaceKinetics& kin)
|
||||
: FuncEval(), m_kin(&kin), m_integ(0),
|
||||
m_atol(1.e-15), m_rtol(1.e-7), m_maxstep(0.0)
|
||||
m_atol(1.e-14), m_rtol(1.e-7), m_maxstep(0.0)
|
||||
{
|
||||
m_integ = new CVodeInt;
|
||||
m_surf = &kin.sphase();
|
||||
m_surf = (SurfPhase*)&kin.thermo(kin.nPhases()-1);
|
||||
|
||||
// use backward differencing, with a full Jacobian computed
|
||||
// numerically, and use a Newton linear iterator
|
||||
|
|
@ -35,7 +35,7 @@ namespace Cantera {
|
|||
m_integ->setProblemType(DENSE + NOJAC);
|
||||
m_integ->setIterator(Newton_Iter);
|
||||
m_nsp = m_surf->nSpecies();
|
||||
m_work.resize(m_kin->nTotal());
|
||||
m_work.resize(m_kin->nTotalSpecies());
|
||||
}
|
||||
|
||||
// overloaded method of FuncEval. Called by the integrator to
|
||||
|
|
@ -69,11 +69,14 @@ namespace Cantera {
|
|||
doublereal rs0 = 1.0/m_surf->siteDensity();
|
||||
m_kin->getNetProductionRates(m_work.begin());
|
||||
int k;
|
||||
int kbulk = m_kin->nTotal() - m_nsp;
|
||||
int kbulk = m_kin->nTotalSpecies() - m_nsp;
|
||||
doublereal sum = 0.0;
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
for (k = 1; k < m_nsp; k++) {
|
||||
ydot[k] = m_work[kbulk + k] * rs0 * m_surf->size(k);
|
||||
sum -= ydot[k];
|
||||
}
|
||||
//if (sum < 0.0) sum = 0.0;
|
||||
ydot[0] = sum;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@
|
|||
|
||||
#include "FuncEval.h"
|
||||
#include "CVode.h"
|
||||
#include "surfKinetics.h"
|
||||
#include "InterfaceKinetics.h"
|
||||
#include "SurfPhase.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ namespace Cantera {
|
|||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
ImplicitSurfChem(SurfKinetics& kin);
|
||||
ImplicitSurfChem(InterfaceKinetics& kin);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -90,8 +91,8 @@ namespace Cantera {
|
|||
*/
|
||||
void updateState(doublereal* y);
|
||||
|
||||
SurfacePhase* m_surf;
|
||||
SurfKinetics* m_kin;
|
||||
SurfPhase* m_surf;
|
||||
InterfaceKinetics* m_kin;
|
||||
int m_nsp;
|
||||
Integrator* m_integ; // pointer to integrator
|
||||
doublereal m_atol, m_rtol; // tolerances
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ namespace Cantera {
|
|||
void SurfPhase::
|
||||
setElectricPotential(doublereal V) {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
m_pe[k] = charge(k)*Faraday;
|
||||
m_pe[k] = charge(k)*Faraday*V;
|
||||
}
|
||||
_updateThermo(true);
|
||||
}
|
||||
|
|
@ -125,7 +125,7 @@ namespace Cantera {
|
|||
}
|
||||
|
||||
void SurfPhase::
|
||||
getCoverages(doublereal* theta) {
|
||||
getCoverages(doublereal* theta) const {
|
||||
getConcentrations(theta);
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
theta[k] *= size(k)/m_n0;
|
||||
|
|
@ -147,7 +147,7 @@ namespace Cantera {
|
|||
m_s0[k] *= GasConstant;
|
||||
m_cp0[k] *= GasConstant;
|
||||
deltaE = m_pe[k];
|
||||
m_h0[k] += deltaE;
|
||||
//m_h0[k] += deltaE;
|
||||
m_mu0[k] = m_h0[k] - tnow*m_s0[k];
|
||||
}
|
||||
m_tlast = tnow;
|
||||
|
|
@ -166,6 +166,7 @@ namespace Cantera {
|
|||
InterfaceKinetics(thermo_t* thermo) :
|
||||
Kinetics(thermo),
|
||||
m_kk(0),
|
||||
m_redo_rates(false),
|
||||
m_nirrev(0),
|
||||
m_nrev(0),
|
||||
m_finalized(false)
|
||||
|
|
@ -177,12 +178,14 @@ namespace Cantera {
|
|||
void InterfaceKinetics::
|
||||
_update_rates_T() {
|
||||
doublereal T = thermo().temperature();
|
||||
if (T != m_kdata->m_temp) {
|
||||
if (T != m_kdata->m_temp || m_redo_rates) {
|
||||
doublereal logT = log(T);
|
||||
m_rates.update(T, logT, m_kdata->m_rfn.begin());
|
||||
correctElectronTransferRates(m_kdata->m_rfn.begin());
|
||||
m_kdata->m_temp = T;
|
||||
updateKc();
|
||||
m_kdata->m_ROP_ok = false;
|
||||
m_redo_rates = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -212,10 +215,14 @@ namespace Cantera {
|
|||
doublereal rrt = 1.0/rt;
|
||||
int np = nPhases();
|
||||
for (n = 0; n < np; n++) {
|
||||
// cout << n << "start = " << m_start[n] << endl;
|
||||
thermo(n).getStandardChemPotentials(m_mu0.begin() + m_start[n]);
|
||||
nsp = thermo(n).nSpecies();
|
||||
for (k = 0; k < nsp; k++) {
|
||||
//cout << ik << "mu0 = " << m_mu0[ik] << endl;
|
||||
m_mu0[ik] -= rt*thermo(n).logStandardConc(k);
|
||||
m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
|
||||
//cout << ik << "mu0 = " << m_mu0[ik] << endl;
|
||||
ik++;
|
||||
}
|
||||
}
|
||||
|
|
@ -228,7 +235,9 @@ namespace Cantera {
|
|||
|
||||
for (i = 0; i < m_nrev; i++) {
|
||||
irxn = m_revindex[i];
|
||||
//cout << "rev " << irxn << " " << m_rkc[irxn] << endl;
|
||||
m_rkc[irxn] = exp(m_rkc[irxn]*rrt);
|
||||
//cout << "rev " << irxn << " " << m_rkc[irxn] << endl;
|
||||
}
|
||||
|
||||
for(i = 0; i != m_nirrev; ++i) {
|
||||
|
|
@ -251,7 +260,14 @@ namespace Cantera {
|
|||
thermo(n).getStandardChemPotentials(m_mu0.begin() + m_start[n]);
|
||||
nsp = thermo(n).nSpecies();
|
||||
for (k = 0; k < nsp; k++) {
|
||||
//cout << thermo(n).id() << " " << thermo(n).speciesName(k)
|
||||
// << " " << m_mu0[ik] << endl;
|
||||
m_mu0[ik] -= rt*thermo(n).logStandardConc(k);
|
||||
m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
|
||||
//if (thermo(n).charge(k) != 0.0) {
|
||||
// cout << thermo(n).id() << " " << thermo(n).speciesName(k)
|
||||
// << " " << m_phi[n] << " " << thermo(n).charge(k) << endl;
|
||||
//}
|
||||
ik++;
|
||||
}
|
||||
}
|
||||
|
|
@ -268,6 +284,41 @@ namespace Cantera {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the equilibrium constants of all reactions, whether
|
||||
* reversible or not.
|
||||
*/
|
||||
void InterfaceKinetics::correctElectronTransferRates(doublereal* kf) {
|
||||
int i;
|
||||
|
||||
int n, nsp, k, ik=0;
|
||||
doublereal rt = GasConstant*thermo(0).temperature();
|
||||
doublereal rrt = 1.0/rt;
|
||||
int np = nPhases();
|
||||
for (n = 0; n < np; n++) {
|
||||
nsp = thermo(n).nSpecies();
|
||||
for (k = 0; k < nsp; k++) {
|
||||
m_pot[ik] = Faraday*thermo(n).charge(k)*m_phi[n];
|
||||
ik++;
|
||||
}
|
||||
}
|
||||
fill(m_rwork.begin(), m_rwork.begin() + m_ii, 0.0);
|
||||
m_reactantStoich.decrementReactions(m_pot.begin(), m_rwork.begin());
|
||||
m_revProductStoich.incrementReactions(m_pot.begin(), m_rwork.begin());
|
||||
m_irrevProductStoich.incrementReactions(m_pot.begin(), m_rwork.begin());
|
||||
doublereal eamod, ea;
|
||||
for (i = 0; i < m_ii; i++) {
|
||||
//loc = m_index[i].second;
|
||||
//if (loc >= 0) {
|
||||
// const Arrhenius& r = m_rates.rateCoeff(m_index[i].second);
|
||||
// ea = GasConstant*r.activationEnergy_R();
|
||||
eamod = 0.5*m_rwork[i];
|
||||
if (m_index[i].second >= 0) kf[i] *= exp(-eamod*rrt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void InterfaceKinetics::updateROP() {
|
||||
|
||||
_update_rates_T();
|
||||
|
|
@ -312,7 +363,6 @@ namespace Cantera {
|
|||
m_kdata->m_ROP_ok = true;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceKinetics::
|
||||
addReaction(const ReactionData& r) {
|
||||
|
||||
|
|
@ -436,9 +486,12 @@ namespace Cantera {
|
|||
m_prxn.resize(m_kk);
|
||||
m_conc.resize(m_kk);
|
||||
m_mu0.resize(m_kk);
|
||||
m_pot.resize(m_kk, 0.0);
|
||||
m_phi.resize(np,0.0);
|
||||
}
|
||||
|
||||
void InterfaceKinetics::finalize() {
|
||||
m_rwork.resize(nReactions());
|
||||
m_finalized = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,11 @@ namespace Cantera {
|
|||
|
||||
virtual int ID() { return cInterfaceKinetics; }
|
||||
|
||||
void setElectricPotential(int n, doublereal V) {
|
||||
m_phi[n] = V;
|
||||
m_redo_rates = true;
|
||||
}
|
||||
|
||||
virtual doublereal reactantStoichCoeff(int k, int i) const {
|
||||
return m_rrxn[k][i];
|
||||
}
|
||||
|
|
@ -153,7 +158,7 @@ namespace Cantera {
|
|||
< m_revindex.end()) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void correctElectronTransferRates(doublereal* kf);
|
||||
void _update_rates_T();
|
||||
void _update_rates_C();
|
||||
|
||||
|
|
@ -162,7 +167,8 @@ namespace Cantera {
|
|||
int m_kk;
|
||||
|
||||
Rate1<Arrhenius> m_rates;
|
||||
|
||||
bool m_redo_rates;
|
||||
|
||||
mutable map<int, pair<int, int> > m_index;
|
||||
|
||||
vector<int> m_irrev;
|
||||
|
|
@ -191,6 +197,9 @@ namespace Cantera {
|
|||
|
||||
vector_fp m_conc;
|
||||
vector_fp m_mu0;
|
||||
vector_fp m_phi;
|
||||
vector_fp m_pot;
|
||||
vector_fp m_rwork;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -251,6 +251,18 @@ namespace Cantera {
|
|||
return -2;
|
||||
}
|
||||
|
||||
thermo_t& speciesPhase(string nm) {
|
||||
int np = m_thermo.size();
|
||||
int k;
|
||||
string id;
|
||||
for (int n = 0; n < np; n++) {
|
||||
k = thermo(n).speciesIndex(nm);
|
||||
if (k >= 0) return thermo(n);
|
||||
}
|
||||
throw CanteraError("speciesPhase", "unknown species "+nm);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare to add reactions.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@ BASE = Elements.o Constituents.o stringUtils.o misc.o importCTML.o plots.o
|
|||
xml.o Phase.o DenseMatrix.o ctml.o funcs.o ctvector.o phasereport.o
|
||||
|
||||
# thermodynamic properties
|
||||
THERMO = $(BASE) ThermoPhase.o IdealGasPhase.o ConstDensityThermo.o SpeciesThermoFactory.o ThermoFactory.o
|
||||
THERMO = $(BASE) ThermoPhase.o IdealGasPhase.o ConstDensityThermo.o SolidCompound.o SpeciesThermoFactory.o ThermoFactory.o
|
||||
|
||||
# homogeneous kinetics
|
||||
KINETICS = GRI_30_Kinetics.o KineticsFactory.o GasKinetics.o FalloffFactory.o GasKineticsWriter.o $(THERMO)
|
||||
|
||||
# heterogeneous kinetics
|
||||
HETEROKIN = InterfaceKinetics.o $(THERMO)
|
||||
HETEROKIN = InterfaceKinetics.o ImplicitSurfChem.o $(THERMO)
|
||||
|
||||
# support for importing from Chemkin-compatible reaction mechanisms
|
||||
CK = $(KINETICS)
|
||||
|
|
|
|||
84
Cantera/src/MetalPhase.h
Normal file
84
Cantera/src/MetalPhase.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
*
|
||||
* @file MetalPhase.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2003 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_METALPHASE_H
|
||||
#define CT_METALPHASE_H
|
||||
|
||||
//#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* @ingroup thermoprops
|
||||
*
|
||||
* Class MetalPhase represents electrons in a metal.
|
||||
*
|
||||
*/
|
||||
class MetalPhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
MetalPhase() {}
|
||||
|
||||
virtual ~MetalPhase() {}
|
||||
|
||||
/**
|
||||
* Equation of state flag.
|
||||
*/
|
||||
virtual int eosType() const { return cMetal; }
|
||||
|
||||
virtual doublereal enthalpy_mole() const { return 0.0; }
|
||||
virtual doublereal intEnergy_mole() const { return 0.0; }
|
||||
virtual doublereal entropy_mole() const { return 0.0; }
|
||||
virtual doublereal gibbs_mole() const { return 0.0; }
|
||||
virtual doublereal cp_mole() const { return 0.0; }
|
||||
virtual doublereal cv_mole() const { return 0.0; }
|
||||
|
||||
virtual void getChemPotentials(doublereal* mu) const {
|
||||
mu[0] = 0.0;
|
||||
}
|
||||
|
||||
virtual void getStandardChemPotentials(doublereal* mu0) const {
|
||||
mu0[0] = 0.0;
|
||||
}
|
||||
|
||||
virtual void getActivityConcentrations(doublereal* c) const {
|
||||
c[0] = 1.0;
|
||||
}
|
||||
|
||||
virtual doublereal standardConcentration(int k=0) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
virtual doublereal logStandardConc(int k=0) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -78,6 +78,10 @@ namespace Cantera {
|
|||
return -1;
|
||||
}
|
||||
|
||||
const R& rateCoeff(int loc) const {
|
||||
return m_rates[loc];
|
||||
}
|
||||
|
||||
void update_C(const doublereal* c) {
|
||||
TYPENAME_KEYWORD vector<R>::iterator b = m_rates.begin();
|
||||
TYPENAME_KEYWORD vector<R>::iterator e = m_rates.end();
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ namespace Cantera {
|
|||
s << ");" << endl;
|
||||
}
|
||||
|
||||
doublereal activationEnergy_R() const {
|
||||
return m_E;
|
||||
}
|
||||
|
||||
protected:
|
||||
doublereal m_logA, m_b, m_E;
|
||||
};
|
||||
|
|
|
|||
50
Cantera/src/SolidCompound.cpp
Normal file
50
Cantera/src/SolidCompound.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
*
|
||||
* @file IdealGasPhase.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "SolidCompound.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
void SolidCompound::initThermo() {
|
||||
m_kk = nSpecies();
|
||||
if (m_kk > 1) {
|
||||
throw CanteraError("initThermo",
|
||||
"solid compounds may only contain one species.");
|
||||
}
|
||||
doublereal tmin = m_spthermo->minTemp();
|
||||
doublereal tmax = m_spthermo->maxTemp();
|
||||
if (tmin > 0.0) m_tmin = tmin;
|
||||
if (tmax > 0.0) m_tmax = tmax;
|
||||
m_p0 = refPressure();
|
||||
|
||||
int leng = m_kk;
|
||||
m_h0_RT.resize(leng);
|
||||
m_cp0_R.resize(leng);
|
||||
m_s0_R.resize(leng);
|
||||
}
|
||||
|
||||
|
||||
void SolidCompound::_updateThermo() const {
|
||||
doublereal tnow = temperature();
|
||||
if (m_tlast != tnow) {
|
||||
m_spthermo->update(tnow, m_cp0_R.begin(), m_h0_RT.begin(),
|
||||
m_s0_R.begin());
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
187
Cantera/src/SolidCompound.h
Normal file
187
Cantera/src/SolidCompound.h
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
*
|
||||
* @file SolidPhase.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2001 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_SOLIDPHASE_H
|
||||
#define CT_SOLIDPHASE_H
|
||||
|
||||
//#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* @ingroup thermoprops
|
||||
*
|
||||
* Class IdealGasPhase represents low-density gases that obey the
|
||||
* ideal gas equation of state. It derives from class ThermoPhase,
|
||||
* and overloads the virtual methods defined there with ones that
|
||||
* use expressions appropriate for ideal gas mixtures.
|
||||
*
|
||||
*/
|
||||
class SolidCompound : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
SolidCompound(): m_tlast(-1.0), m_tmin(0.0), m_tmax(0.0),
|
||||
m_press(OneAtm), m_p0(OneAtm) {}
|
||||
|
||||
virtual ~SolidCompound() {}
|
||||
|
||||
/**
|
||||
* Equation of state flag. Returns the value cIdealGas, defined
|
||||
* in mix_defs.h.
|
||||
*/
|
||||
virtual int eosType() const { return cSolidCompound; }
|
||||
|
||||
|
||||
/**
|
||||
* @name Molar Thermodynamic Properties
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Molar enthalpy. Units: J/kmol.
|
||||
*/
|
||||
virtual doublereal enthalpy_mole() const {
|
||||
double hh = intEnergy_mole() + m_press / molarDensity();
|
||||
return hh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar internal energy. J/kmol.
|
||||
*/
|
||||
virtual doublereal intEnergy_mole() const {
|
||||
_updateThermo();
|
||||
// cout << "intEnergy: " << m_h0_RT[0] << " " << m_p0/molarDensity()
|
||||
// << endl;
|
||||
return GasConstant * temperature() * m_h0_RT[0]
|
||||
- m_p0 / molarDensity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar entropy. Units: J/kmol/K.
|
||||
*/
|
||||
virtual doublereal entropy_mole() const {
|
||||
_updateThermo();
|
||||
//cout << "s/r = " << m_s0_R[0] << endl;
|
||||
return GasConstant * m_s0_R[0];
|
||||
}
|
||||
|
||||
|
||||
virtual doublereal gibbs_mole() const {
|
||||
return enthalpy_mole() - temperature() * entropy_mole();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Molar heat capacity at constant pressure. Units: J/kmol/K.
|
||||
*/
|
||||
virtual doublereal cp_mole() const {
|
||||
_updateThermo();
|
||||
return GasConstant * m_cp0_R[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar heat capacity at constant volume. Units: J/kmol/K.
|
||||
*/
|
||||
virtual doublereal cv_mole() const {
|
||||
return cp_mole();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* @name Mechanical Equation of State
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pressure. Units: Pa.
|
||||
*/
|
||||
virtual doublereal pressure() const {
|
||||
return m_press;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pressure at constant temperature. Units: Pa.
|
||||
*/
|
||||
virtual void setPressure(doublereal p) {
|
||||
m_press = p;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
virtual void getChemPotentials(doublereal* mu) const {
|
||||
mu[0] = gibbs_mole();
|
||||
}
|
||||
|
||||
virtual void getStandardChemPotentials(doublereal* mu0) const {
|
||||
mu0[0] = gibbs_mole();
|
||||
//cout << m_h0_RT[0] << " " << m_s0_R[0] << endl;
|
||||
//cout << "std chem pot = " << mu0[0] << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the array of generalized
|
||||
* concentrations. For a solid compound, there is only one
|
||||
* species, and the generalized concentration is 1.0.
|
||||
*/
|
||||
virtual void getActivityConcentrations(doublereal* c) const {
|
||||
c[0] = 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard concentration. This is defined as the concentration
|
||||
* by which the generalized concentration is normalized to produce
|
||||
* the activity.
|
||||
*/
|
||||
virtual doublereal standardConcentration(int k=0) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
virtual doublereal logStandardConc(int k=0) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
virtual void initThermo();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_kk;
|
||||
doublereal m_tmin, m_tmax, m_p0, m_press;
|
||||
|
||||
mutable doublereal m_tlast;
|
||||
mutable array_fp m_h0_RT;
|
||||
mutable array_fp m_cp0_R;
|
||||
mutable array_fp m_s0_R;
|
||||
|
||||
private:
|
||||
|
||||
void _updateThermo() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ namespace Cantera {
|
|||
void setSiteDensity(doublereal n0);
|
||||
void setElectricPotential(doublereal V);
|
||||
void setCoverages(const doublereal* theta);
|
||||
void getCoverages(doublereal* theta);
|
||||
void getCoverages(doublereal* theta) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -21,15 +21,19 @@
|
|||
#include "IdealGasPhase.h"
|
||||
#include "ConstDensityThermo.h"
|
||||
#include "SurfPhase.h"
|
||||
#include "MetalPhase.h"
|
||||
#include "SolidCompound.h"
|
||||
#include "importCTML.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
ThermoFactory* ThermoFactory::__factory = 0;
|
||||
|
||||
static int ntypes = 3;
|
||||
static string _types[] = {"IdealGas", "Incompressible", "Surface"};
|
||||
static int _itypes[] = {cIdealGas, cIncompressible, cSurf};
|
||||
static int ntypes = 5;
|
||||
static string _types[] = {"IdealGas", "Incompressible",
|
||||
"Surface", "Metal", "SolidCompound"};
|
||||
static int _itypes[] = {cIdealGas, cIncompressible,
|
||||
cSurf, cMetal, cSolidCompound};
|
||||
|
||||
|
||||
ThermoPhase* ThermoFactory::newThermoPhase(string model) {
|
||||
|
|
@ -55,6 +59,14 @@ namespace Cantera {
|
|||
th = new SurfPhase;
|
||||
break;
|
||||
|
||||
case cMetal:
|
||||
th = new MetalPhase;
|
||||
break;
|
||||
|
||||
case cSolidCompound:
|
||||
th = new SolidCompound;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw CanteraError("newThermo",
|
||||
"newThermo: unknown equation of state: "+model);
|
||||
|
|
@ -99,22 +111,23 @@ namespace Cantera {
|
|||
switch (ieos) {
|
||||
|
||||
case cIdealGas:
|
||||
// Ideal gas
|
||||
th = new IdealGasPhase;
|
||||
break;
|
||||
|
||||
case cIncompressible:
|
||||
// getFloats(eos,d);
|
||||
//dens = d["density"];
|
||||
th = new ConstDensityThermo;
|
||||
//th->setParameters(1, &dens);
|
||||
break;
|
||||
|
||||
case cSurf:
|
||||
//getFloats(eos,d);
|
||||
//dens = d["site_density"];
|
||||
th = new SurfPhase;
|
||||
//th->setParameters(1, &dens);
|
||||
break;
|
||||
|
||||
case cMetal:
|
||||
th = new MetalPhase;
|
||||
break;
|
||||
|
||||
case cSolidCompound:
|
||||
th = new SolidCompound;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -122,8 +135,10 @@ namespace Cantera {
|
|||
"newThermo: unknown equation of state: "+eostype);
|
||||
}
|
||||
th->setSpeciesThermo(spthermo);
|
||||
|
||||
// import the phase specification
|
||||
importPhase(node, th);
|
||||
|
||||
return th;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ using namespace std;
|
|||
#include "ReactionData.h"
|
||||
#include "global.h"
|
||||
#include "stringUtils.h"
|
||||
#include "GasKineticsWriter.h"
|
||||
|
||||
#include "xml.h"
|
||||
#include "ctml.h"
|
||||
|
|
@ -40,6 +41,8 @@ using namespace ctml;
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
GasKineticsWriter* writer = 0;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
typedef vector<XML_Node*> nodeset_t;
|
||||
|
|
@ -191,15 +194,15 @@ namespace Cantera {
|
|||
* Define a map and get all of the floats in the
|
||||
* current XML species block
|
||||
*/
|
||||
map<string, double> fd;
|
||||
getFloats(s, fd);
|
||||
//map<string, double> fd;
|
||||
//getFloats(s, fd);
|
||||
doublereal chrg = 0.0;
|
||||
if (s.hasChild("charge")) chrg = getFloat(s, "charge");
|
||||
doublereal sz = 1.0;
|
||||
if (s.hasChild("size")) sz = getFloat(s, "size");
|
||||
|
||||
/*
|
||||
* Set a default for the size parameter to one
|
||||
*/
|
||||
if (fd["size"] == 0.0) fd["size"] = 1.0;
|
||||
p.addUniqueSpecies(s["name"], ecomp.begin(),
|
||||
fd["charge"], fd["size"]);
|
||||
chrg, sz);
|
||||
|
||||
// get thermo
|
||||
XML_Node& thermo = s.child("thermo");
|
||||
|
|
@ -391,7 +394,8 @@ namespace Cantera {
|
|||
vector_fp coeff(3);
|
||||
getArrhenius(c, order, coeff[0], coeff[1], coeff[2]);
|
||||
if (order == 0) order = nr;
|
||||
if (order == nr || rdata.reactionType == THREE_BODY_RXN)
|
||||
if (order == nr || rdata.reactionType == THREE_BODY_RXN
|
||||
|| rdata.reactionType == ELEMENTARY_RXN)
|
||||
chigh = coeff;
|
||||
else if (order == nr + 1) clow = coeff;
|
||||
else {
|
||||
|
|
@ -401,6 +405,15 @@ namespace Cantera {
|
|||
"wrong Arrhenius coeff order");
|
||||
}
|
||||
}
|
||||
// else if (nm == "Stick") {
|
||||
// vector_fp coeff(3);
|
||||
// string spname = c["species"];
|
||||
// ThermoPhase& th = kin.speciesPhase(spname);
|
||||
// int isp = th.speciesIndex(spname);
|
||||
// double mw = th.molecularWeights()[isp];
|
||||
// cbar = sqrt((8.0*GasConstant)/(Pi*mw));
|
||||
//
|
||||
// }
|
||||
else if (nm == "falloff") {
|
||||
getFalloff(c, rdata);
|
||||
}
|
||||
|
|
@ -501,11 +514,21 @@ namespace Cantera {
|
|||
"wrong equation of state type");
|
||||
}
|
||||
}
|
||||
else if (eos["model"] == "SolidCompound") {
|
||||
if (th->eosType() == cSolidCompound) {
|
||||
doublereal rho = getFloat(eos, "density", "-");
|
||||
th->setDensity(rho);
|
||||
}
|
||||
else {
|
||||
throw CanteraError("importCTML",
|
||||
"wrong equation of state type");
|
||||
}
|
||||
}
|
||||
else if (eos["model"] == "Surface") {
|
||||
if (th->eosType() == cSurf) {
|
||||
map<string, doublereal> d;
|
||||
//map<string, doublereal> d;
|
||||
//getFloats(eos, d);
|
||||
doublereal n = fpValue(eos("site_density"));
|
||||
doublereal n = getFloat(eos, "site_density", "-");
|
||||
th->setParameters(1, &n);
|
||||
}
|
||||
else {
|
||||
|
|
@ -685,12 +708,16 @@ namespace Cantera {
|
|||
|
||||
getRateCoefficient(r.child("rateCoeff"), kin, rdata);
|
||||
kin.addReaction(rdata);
|
||||
//if (writer) writer->addReaction(rdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool installReactionArrays(XML_Node& p, Kinetics& kin,
|
||||
string default_phase) {
|
||||
|
||||
writer = new GasKineticsWriter;
|
||||
|
||||
vector<XML_Node*> rarrays;
|
||||
int itot = 0;
|
||||
p.getChildren("reactionArray",rarrays);
|
||||
|
|
@ -738,6 +765,12 @@ namespace Cantera {
|
|||
}
|
||||
}
|
||||
kin.finalize();
|
||||
ofstream fwrite("mech.cpp");
|
||||
//writer->writeGetNetProductionRates(cout, kin.nTotalSpecies(),
|
||||
// kin.nReactions());
|
||||
fwrite.close();
|
||||
delete writer;
|
||||
writer = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ namespace Cantera {
|
|||
const int cIdealGas = 1;
|
||||
const int cIncompressible = 2;
|
||||
const int cSurf = 3;
|
||||
const int cMetal = 4;
|
||||
const int cSolidCompound = 5;
|
||||
|
||||
// kinetic manager types
|
||||
const int cGasKinetics = 2;
|
||||
|
|
|
|||
|
|
@ -107,10 +107,10 @@ namespace Cantera {
|
|||
m_nv = nv;
|
||||
m_max.resize(m_nv, 0.0);
|
||||
m_min.resize(m_nv, 0.0);
|
||||
m_rtol_ss.resize(m_nv, 0.0);
|
||||
m_atol_ss.resize(m_nv, 0.0);
|
||||
m_rtol_ts.resize(m_nv, 0.0);
|
||||
m_atol_ts.resize(m_nv, 0.0);
|
||||
m_rtol_ss.resize(m_nv, 1.0e-8);
|
||||
m_atol_ss.resize(m_nv, 1.0e-15);
|
||||
m_rtol_ts.resize(m_nv, 1.0e-8);
|
||||
m_atol_ts.resize(m_nv, 1.0e-15);
|
||||
m_points = np;
|
||||
m_z.resize(np, 0.0);
|
||||
m_slast.resize(m_nv * m_points, 0.0);
|
||||
|
|
|
|||
|
|
@ -97,14 +97,17 @@ namespace Cantera {
|
|||
const doublereal* step, OneDim& r) const {
|
||||
doublereal f, sum = 0.0;//, fmx = 0.0;
|
||||
int n;
|
||||
int nd = r.nDomains();
|
||||
int nd = r.nDomains();
|
||||
for (n = 0; n < nd; n++) {
|
||||
f = norm_square(x + r.start(n), step + r.start(n),
|
||||
r.domain(n));
|
||||
sum += f;
|
||||
// if (f > fmx) fmx = f;
|
||||
// cout << "n = " << n << " f = " << f << endl;
|
||||
}
|
||||
//cout << "sum = " << sum << endl;
|
||||
//cout << "r.size() = " << r.size() << endl;
|
||||
sum /= r.size();
|
||||
//cout << "sum = " << sum << " " << sqrt(sum) << endl;
|
||||
return sqrt(sum);
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +124,11 @@ namespace Cantera {
|
|||
for (n = 0; n < sz; n++) {
|
||||
step[n] = -step[n];
|
||||
}
|
||||
jac.solve(sz, step, step);
|
||||
|
||||
#undef DEBUG_STEP
|
||||
#ifdef DEBUG_STEP
|
||||
bool ok = false;
|
||||
Domain1D* d;
|
||||
if (!ok) {
|
||||
for (n = 0; n < sz; n++) {
|
||||
|
|
@ -132,10 +139,10 @@ namespace Cantera {
|
|||
r.pointDomain(n)->componentName(n - d->loc() - nvd*pt)
|
||||
<< " " << x[n] << " " << step[n] << endl;
|
||||
}
|
||||
if (!ok) throw "not ok";
|
||||
//if (!ok) throw "not ok";
|
||||
}
|
||||
#endif
|
||||
jac.solve(sz, step, step);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -336,9 +336,9 @@ namespace Cantera {
|
|||
}
|
||||
}
|
||||
}
|
||||
//else {
|
||||
// throw CanteraError("refine","keepPoint is false at m = "+int2str(m));
|
||||
//}
|
||||
else {
|
||||
throw CanteraError("refine","keepPoint is false at m = "+int2str(m));
|
||||
}
|
||||
}
|
||||
dsize.push_back(znew.size() - nstart);
|
||||
}
|
||||
|
|
|
|||
634
Cantera/src/oneD/Solid1D.cpp
Normal file
634
Cantera/src/oneD/Solid1D.cpp
Normal file
|
|
@ -0,0 +1,634 @@
|
|||
/**
|
||||
* @file Solid.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2003 California Institute of Technology
|
||||
|
||||
|
||||
// turn off warnings under Windows
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "Solid1D.h"
|
||||
#include "../ArrayViewer.h"
|
||||
#include "ctml.h"
|
||||
#include "MultiJac.h"
|
||||
|
||||
using namespace ctml;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
int Solid1D::c_T_loc = 0;
|
||||
int Solid1D::c_phi_loc = 1;
|
||||
int Solid1D::c_Y_loc = 2;
|
||||
|
||||
|
||||
Solid1D::Solid1D(ThermoPhase* ph, int nsp, int points) :
|
||||
Domain1D(nsp+1, points),
|
||||
m_nsp(nsp),
|
||||
m_thermo(0),
|
||||
m_kin(0),
|
||||
m_trans(0),
|
||||
m_jac(0),
|
||||
m_ok(false),
|
||||
{
|
||||
m_type = cSolidType;
|
||||
|
||||
m_points = points;
|
||||
m_thermo = ph;
|
||||
|
||||
if (ph == 0) return; // used to create a dummy object
|
||||
|
||||
int nsp2 = m_thermo->nSpecies();
|
||||
if (nsp2 != m_nsp) {
|
||||
m_nsp = nsp2;
|
||||
Domain1D::resize(m_nsp+1, points);
|
||||
}
|
||||
|
||||
|
||||
// make a local copy of the species molecular weight vector
|
||||
m_wt = m_thermo->molecularWeights();
|
||||
|
||||
m_nv = m_nsp + 1;
|
||||
|
||||
// turn off the energy equation at all points
|
||||
m_do_energy.resize(m_points,false);
|
||||
m_do_gauss.resize(m_points,false);
|
||||
m_do_species.resize(m_nsp,false);
|
||||
|
||||
m_diff.resize(m_nsp*m_points);
|
||||
m_flux.resize(m_nsp,m_points);
|
||||
m_wdot.resize(m_nsp,m_points, 0.0);
|
||||
m_ybar.resize(m_nsp);
|
||||
|
||||
|
||||
//-------------- default solution bounds --------------------
|
||||
|
||||
vector_fp vmin(m_nv), vmax(m_nv);
|
||||
|
||||
// temperature bounds
|
||||
vmin[c_T_loc] = 200.0;
|
||||
vmax[c_T_loc]= 1.e9;
|
||||
|
||||
// mass fraction bounds
|
||||
int k;
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
vmin[c_Y_loc + k] = -1.0e-5;
|
||||
vmax[c_Y_loc + k] = 1.0e5;
|
||||
}
|
||||
setBounds(vmin.size(), vmin.begin(), vmax.size(), vmax.begin());
|
||||
|
||||
|
||||
//-------------------- default error tolerances ----------------
|
||||
vector_fp rtol(m_nv, 1.0e-8);
|
||||
vector_fp atol(m_nv, 1.0e-15);
|
||||
setTolerances(rtol.size(), rtol.begin(), atol.size(), atol.begin(),false);
|
||||
setTolerances(rtol.size(), rtol.begin(), atol.size(), atol.begin(),true);
|
||||
|
||||
//-------------------- grid refinement -------------------------
|
||||
m_refiner->setActive(c_T_loc, false);
|
||||
|
||||
vector_fp gr;
|
||||
for (int ng = 0; ng < m_points; ng++) gr.push_back(1.0*ng/m_points);
|
||||
setupGrid(m_points, gr.begin());
|
||||
setID("solid");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the grid size. Called after grid refinement.
|
||||
*/
|
||||
void Solid1D::resize(int points) {
|
||||
Domain1D::resize(m_nv, points);
|
||||
|
||||
m_rho.resize(m_points, 0.0);
|
||||
m_wtm.resize(m_points, 0.0);
|
||||
m_cp.resize(m_points, 0.0);
|
||||
m_tcon.resize(m_points, 0.0);
|
||||
m_cdens.resize(m_points, 0.0);
|
||||
m_diff.resize(m_nsp*m_points);
|
||||
|
||||
m_flux.resize(m_nsp,m_points);
|
||||
m_wdot.resize(m_nsp,m_points, 0.0);
|
||||
|
||||
m_do_energy.resize(m_points,false);
|
||||
m_do_gauss.resize(m_points,false);
|
||||
m_do_species.resize(m_nsp,false);
|
||||
|
||||
m_fixedtemp.resize(m_points);
|
||||
m_fixedphi.resize(m_points);
|
||||
|
||||
m_dz.resize(m_points-1);
|
||||
m_z.resize(m_points);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Solid1D::setupGrid(int n, const doublereal* z) {
|
||||
resize(n);
|
||||
int j;
|
||||
m_z[0] = z[0];
|
||||
for (j = 1; j < m_points; j++) {
|
||||
m_z[j] = z[j];
|
||||
m_dz[j-1] = m_z[j] - m_z[j-1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Install a transport manager.
|
||||
*/
|
||||
void Solid1D::setTransport(Transport& trans) {
|
||||
m_trans = &trans;
|
||||
|
||||
if (m_trans->model() != cSolidTransport) {
|
||||
throw CanteraError("setTransport","unknown transport model.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the solid object state to be consistent with the solution at
|
||||
* point j.
|
||||
*/
|
||||
void Solid1D::setThermoState(const doublereal* x,int j) {
|
||||
m_thermo->setTemperature(T(x,j));
|
||||
m_thermo->setElectricPotential(phi(x,j));
|
||||
const doublereal* yy = x + m_nv*j + 1;
|
||||
m_thermo->setMassFractions_NoNorm(yy);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the state to be consistent with the solution at the
|
||||
* midpoint between j and j + 1.
|
||||
*/
|
||||
void Solid1D::setStateAtMidpoint(const doublereal* x,int j) {
|
||||
m_thermo->setTemperature(0.5*(T(x,j)+T(x,j+1)));
|
||||
m_thermo->setElectricPotential(0.5*(phi(x,j)+phi(x,j+1)));
|
||||
const doublereal* yyj = x + m_nv*j + 1;
|
||||
const doublereal* yyjp = x + m_nv*(j+1) + 1;
|
||||
for (int k = 0; k < m_nsp; k++)
|
||||
m_ybar[k] = 0.5*(yyj[k] + yyjp[k]);
|
||||
m_thermo->setMassFractions_NoNorm(m_ybar.begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Solid1D::eval(int jg, doublereal* xg,
|
||||
doublereal* rg, integer* diagg, doublereal rdt) {
|
||||
|
||||
// if evaluating a Jacobian, and the global point is outside
|
||||
// the domain of influence for this domain, then skip
|
||||
// evaluating the residual
|
||||
if (jg >=0 && (jg < firstPoint() - 1 || jg > lastPoint() + 1)) return;
|
||||
|
||||
// if evaluating a Jacobian, compute the steady-state residual
|
||||
if (jg >= 0) rdt = 0.0;
|
||||
|
||||
// start of local part of global arrays
|
||||
doublereal* x = xg + loc();
|
||||
doublereal* rsd = rg + loc();
|
||||
integer* diag = diagg + loc();
|
||||
|
||||
int jmin, jmax, jpt;
|
||||
jpt = jg - firstPoint();
|
||||
|
||||
if (jg < 0) { // evaluate all points
|
||||
jmin = 0;
|
||||
jmax = m_points - 1;
|
||||
}
|
||||
else { // evaluate points for Jacobian
|
||||
jmin = max(jpt-1, 0);
|
||||
jmax = min(jpt+1,m_points-1);
|
||||
}
|
||||
|
||||
// properties are computed for grid points from j0 to j1
|
||||
int j0 = max(jmin-1,0);
|
||||
int j1 = min(jmax+1,m_points-1);
|
||||
|
||||
|
||||
int j, k;
|
||||
|
||||
|
||||
//-----------------------------------------------------
|
||||
// update properties
|
||||
//-----------------------------------------------------
|
||||
|
||||
// thermodynamic properties only if a Jacobian is
|
||||
// not being evaluated
|
||||
if (jpt < 0)
|
||||
updateThermo(x, j0, j1);
|
||||
|
||||
// update transport properties only if a Jacobian is
|
||||
// not being evaluated
|
||||
if (jpt < 0)
|
||||
updateTransport(x, j0, j1);
|
||||
|
||||
// update the species diffusive mass fluxes whether or not a
|
||||
// Jacobian is being evaluated
|
||||
updateDiffFluxes(x, j0, j1);
|
||||
|
||||
for (j = j0; j <= j1; j++) {
|
||||
setThermoState(j);
|
||||
m_cdens[j] = m_thermo->chargeDensity();
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
// evaluate the residual equations at all required
|
||||
// grid points
|
||||
//----------------------------------------------------
|
||||
|
||||
for (j = jmin; j <= jmax; j++) {
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
// left boundary
|
||||
//----------------------------------------------
|
||||
|
||||
if (j == 0) {
|
||||
rsd[index(c_T_loc,0)] = T(x,0);
|
||||
rsd[index(c_phi_loc,0)] = phi(x,0);
|
||||
|
||||
// The default boundary condition for species is zero
|
||||
// flux. However, the boundary object may modify
|
||||
// this.
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
rsd[index(c_Y_loc + k, 0)] = - m_flux(k,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
//
|
||||
// right boundary
|
||||
//
|
||||
//----------------------------------------------
|
||||
|
||||
else if (j == m_points - 1) {
|
||||
rsd[index(c_T_loc,j)] = T(x,j);
|
||||
rsd[index(c_phi_loc,j)] = phi(x,j);
|
||||
doublereal sum = 0.0;
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
sum += Y(x,k,j);
|
||||
rsd[index(k+c_Y_loc,j)] = m_flux(k,j-1);
|
||||
}
|
||||
rsd[index(c_Y_loc,j)] = 1.0 - sum;
|
||||
diag[index(c_Y_loc,j)] = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// interior points
|
||||
//------------------------------------------
|
||||
|
||||
else {
|
||||
|
||||
//-------------------------------------------------
|
||||
// Species equations
|
||||
//
|
||||
// \rho u dY_k/dz + dJ_k/dz + M_k\omega_k
|
||||
//
|
||||
//-------------------------------------------------
|
||||
getWdot(x,j);
|
||||
|
||||
doublereal convec, diffus;
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
diffus = 2.0*(m_flux(k,j) - m_flux(k,j-1))
|
||||
/(z(j+1) - z(j-1));
|
||||
rsd[index(c_Y_loc + k, j)]
|
||||
= (m_wt[k]*(wdot(k,j) )
|
||||
- diffus)/m_rho[j]
|
||||
- rdt*(Y(x,k,j) - Y_prev(k,j));
|
||||
diag[index(c_Y_loc + k, j)] = 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// energy equation
|
||||
//-----------------------------------------------
|
||||
|
||||
if (m_do_energy[j]) {
|
||||
|
||||
rsd[index(c_T_loc, j)] = - divHeatFlux(x,j);
|
||||
rsd[index(c_T_loc, j)] /= (m_rho[j]*m_cp[j]);
|
||||
|
||||
rsd[index(c_T_loc, j)] -= rdt*(T(x,j) - T_prev(j));
|
||||
diag[index(c_T_loc, j)] = 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Gauss's equation
|
||||
//----------------------------------------------
|
||||
rsd[index(c_phi_loc, j)] = m_cdens[j] - divDisplCurr(x,j);
|
||||
|
||||
}
|
||||
|
||||
// residual equations if the energy or species equations
|
||||
// are disabled
|
||||
|
||||
if (!m_do_energy[j]) {
|
||||
rsd[index(c_T_loc, j)] = T(x,j) - T_fixed(j);
|
||||
diag[index(c_T_loc, j)] = 0;
|
||||
}
|
||||
if (!m_do_gauss[j]) {
|
||||
rsd[index(c_phi_loc, j)] = phi(x,j) - phi_fixed(j);
|
||||
diag[index(c_phi_loc, j)] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the transport properties at grid points in the range
|
||||
* from j0 to j1, based on solution x.
|
||||
*/
|
||||
void Surf1D::updateTransport(doublereal* x,int j0, int j1) {
|
||||
int j;
|
||||
for (j = j0; j < j1; j++) {
|
||||
setStateAtMidpoint(x,j);
|
||||
m_trans->getMixDiffCoeffs(m_diff.begin() + j*m_nsp);
|
||||
m_tcon[j] = m_trans->thermalConductivity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print the solution.
|
||||
*/
|
||||
void Solid1D::showSolution(const doublereal* x) {
|
||||
int nn = m_nv/5;
|
||||
int i, j, n;
|
||||
char* buf = new char[100];
|
||||
|
||||
// The mean molecular weight is needed to convert
|
||||
updateThermo(x, 0, m_points-1);
|
||||
|
||||
for (i = 0; i < nn; i++) {
|
||||
drawline();
|
||||
sprintf(buf, "\n z ");
|
||||
writelog(buf);
|
||||
for (n = 0; n < 5; n++) {
|
||||
sprintf(buf, " %10s ",componentName(i*5 + n).c_str());
|
||||
writelog(buf);
|
||||
}
|
||||
drawline();
|
||||
for (j = 0; j < m_points; j++) {
|
||||
sprintf(buf, "\n %10.4g ",m_z[j]);
|
||||
writelog(buf);
|
||||
for (n = 0; n < 5; n++) {
|
||||
sprintf(buf, " %10.4g ",component(x, i*5+n,j));
|
||||
writelog(buf);
|
||||
}
|
||||
}
|
||||
writelog("\n");
|
||||
}
|
||||
int nrem = m_nv - 5*nn;
|
||||
drawline();
|
||||
sprintf(buf, "\n z ");
|
||||
writelog(buf);
|
||||
for (n = 0; n < nrem; n++) {
|
||||
sprintf(buf, " %10s ", componentName(nn*5 + n).c_str());
|
||||
writelog(buf);
|
||||
}
|
||||
drawline();
|
||||
for (j = 0; j < m_points; j++) {
|
||||
sprintf(buf, "\n %10.4g ",m_z[j]);
|
||||
writelog(buf);
|
||||
for (n = 0; n < nrem; n++) {
|
||||
sprintf(buf, " %10.4g ",component(x, nn*5+n,j));
|
||||
writelog(buf);
|
||||
}
|
||||
}
|
||||
writelog("\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the diffusive mass fluxes.
|
||||
*/
|
||||
void Solid1D::updateDiffFluxes(const doublereal* x, int j0, int j1) {
|
||||
int j, k, m;
|
||||
doublereal sum, wtm, rho, dz, gradlogT, s;
|
||||
doublereal dphidz, a1;
|
||||
for (j = j0; j < j1; j++) {
|
||||
sum = 0.0;
|
||||
wtm = m_wtm[j];
|
||||
rho = density(j);
|
||||
dz = z(j+1) - z(j);
|
||||
dphidz = (phi(x,j+1) - phi(x,j))/dz;
|
||||
a1 = rho*Faraday*dphidz/(GasConstant * T(x,j));
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
m_flux(k,j) = m_wt[k]*(rho*m_diff[k+m_nsp*j]/wtm);
|
||||
m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
|
||||
m_flux(k,j) += a1*0.5*(Y(x,k,j)
|
||||
+ Y(x,k,j+1))*m_diff[k+m_nsp*j]*m_charge[k];
|
||||
sum -= m_flux(k,j);
|
||||
}
|
||||
for (k = 0; k < m_nsp; k++) m_flux(k,j) += Y(x,k,j)*sum;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
void Solid1D::outputTEC(ostream &s, const doublereal* x,
|
||||
string title, int zone) {
|
||||
int j,k;
|
||||
s << "TITLE = \"" + title + "\"" << endl;
|
||||
s << "VARIABLES = \"Z (m)\"" << endl;
|
||||
s << "\"T (K)\"" << endl;
|
||||
s << "\"phi (V)\"" << endl;
|
||||
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
s << "\"" << m_thermo->speciesName(k) << "\"" << endl;
|
||||
}
|
||||
s << "ZONE T=\"c" << zone << "\"" << endl;
|
||||
s << " I=" << m_points << ",J=1,K=1,F=POINT" << endl;
|
||||
s << "DT=(SINGLE SINGLE";
|
||||
for (k = 0; k < m_nsp; k++) s << " SINGLE";
|
||||
s << " )" << endl;
|
||||
for (j = 0; j < m_points; j++) {
|
||||
s << z(j) << " ";
|
||||
for (k = 0; k < m_nv; k++) {
|
||||
s << component(x, k, j) << " ";
|
||||
}
|
||||
s << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string Solid1D::componentName(int n) const {
|
||||
switch(n) {
|
||||
case c_T_loc: return "T";
|
||||
case c_phi_loc: return "phi";
|
||||
default:
|
||||
if (n >= (int) 1 && n < (int) (c_Y_loc + m_nsp)) {
|
||||
return m_thermo->speciesName(n - 1);
|
||||
}
|
||||
else
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Solid1D::restore(XML_Node& dom, doublereal* soln) {
|
||||
|
||||
vector<string> ignored;
|
||||
int nsp = m_thermo->nSpecies();
|
||||
vector_int did_species(nsp, 0);
|
||||
|
||||
vector<XML_Node*> str;
|
||||
dom.getChildren("string",str);
|
||||
int nstr = str.size();
|
||||
for (int istr = 0; istr < nstr; istr++) {
|
||||
XML_Node& nd = *str[istr];
|
||||
writelog(nd["title"]+": "+nd.value()+"\n");
|
||||
}
|
||||
|
||||
map<string, double> params;
|
||||
getFloats(dom, params);
|
||||
|
||||
vector<XML_Node*> d;
|
||||
dom.child("grid_data").getChildren("floatArray",d);
|
||||
int nd = d.size();
|
||||
|
||||
vector_fp x;
|
||||
int n, np, j, ks, k;
|
||||
string nm;
|
||||
bool readgrid = false, wrote_header = false;
|
||||
for (n = 0; n < nd; n++) {
|
||||
XML_Node& fa = *d[n];
|
||||
nm = fa["title"];
|
||||
if (nm == "z") {
|
||||
getFloatArray(fa,x,false);
|
||||
np = x.size();
|
||||
writelog("Grid contains "+int2str(np)+
|
||||
" points.\n");
|
||||
readgrid = true;
|
||||
|
||||
// note that setupGrid also resizes the domain.
|
||||
setupGrid(np, x.begin());
|
||||
}
|
||||
}
|
||||
if (!readgrid) {
|
||||
throw CanteraError("Solid1D::restore",
|
||||
"domain contains no grid points.");
|
||||
}
|
||||
|
||||
writelog("Importing datasets:\n");
|
||||
for (n = 0; n < nd; n++) {
|
||||
XML_Node& fa = *d[n];
|
||||
nm = fa["title"];
|
||||
getFloatArray(fa,x,false);
|
||||
if (nm == "z") {
|
||||
; // already read grid
|
||||
}
|
||||
else if (nm == "T") {
|
||||
writelog("temperature ");
|
||||
if ((int) x.size() == np) {
|
||||
for (j = 0; j < np; j++)
|
||||
soln[index(c_T_loc,j)] = x[j];
|
||||
|
||||
// For fixed-temperature simulations, use the imported temperature profile by default.
|
||||
// If this is not desired, call setFixedTempProfile *after* restoring the solution.
|
||||
vector_fp zz(np);
|
||||
for (int jj = 0; jj < np; jj++) zz[jj] = (grid(jj) - zmin())/(zmax() - zmin());
|
||||
setFixedTempProfile(zz, x);
|
||||
}
|
||||
else goto error;
|
||||
}
|
||||
else if (nm == "phi") {
|
||||
writelog("potential ");
|
||||
if ((int) x.size() == np) {
|
||||
for (j = 0; j < np; j++)
|
||||
soln[index(c_phi_loc,j)] = x[j];
|
||||
}
|
||||
else goto error;
|
||||
}
|
||||
else if (m_thermo->speciesIndex(nm) >= 0) {
|
||||
writelog(nm+" ");
|
||||
if ((int) x.size() == np) {
|
||||
k = m_thermo->speciesIndex(nm);
|
||||
did_species[k] = 1;
|
||||
for (j = 0; j < np; j++)
|
||||
soln[index(k+c_Y_loc,j)] = x[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
ignored.push_back(nm);
|
||||
}
|
||||
|
||||
if (ignored.size() != 0) {
|
||||
writelog("\n\n");
|
||||
writelog("Ignoring datasets:\n");
|
||||
int nn = ignored.size();
|
||||
for (int n = 0; n < nn; n++) {
|
||||
writelog(ignored[n]+" ");
|
||||
}
|
||||
}
|
||||
|
||||
for (ks = 0; ks < nsp; ks++) {
|
||||
if (did_species[ks] == 0) {
|
||||
if (!wrote_header) {
|
||||
writelog("Missing data for species:\n");
|
||||
wrote_header = true;
|
||||
}
|
||||
writelog(m_thermo->speciesName(ks)+" ");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
error:
|
||||
throw CanteraError("Solid1D::restore","Data size error");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Solid1D::save(XML_Node& o, doublereal* sol) {
|
||||
int k;
|
||||
|
||||
ArrayViewer soln(m_nv, m_points, sol + loc());
|
||||
|
||||
XML_Node& flow = (XML_Node&)o.addChild("domain");
|
||||
flow.addAttribute("type",flowType());
|
||||
flow.addAttribute("id",m_id);
|
||||
flow.addAttribute("points",m_points);
|
||||
flow.addAttribute("components",m_nv);
|
||||
|
||||
if (m_desc != "") addString(flow,"description",m_desc);
|
||||
XML_Node& gv = flow.addChild("grid_data");
|
||||
addFloatArray(gv,"z",m_z.size(),m_z.begin(),
|
||||
"m","length");
|
||||
vector_fp x(soln.nColumns());
|
||||
|
||||
soln.getRow(c_T_loc,x.begin());
|
||||
addFloatArray(gv,"T",x.size(),x.begin(),"K","temperature",0.0);
|
||||
|
||||
soln.getRow(c_phi_loc,x.begin());
|
||||
addFloatArray(gv,"phi",x.size(),x.begin(),"V","potential",0.0);
|
||||
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
soln.getRow(c_Y_loc+k,x.begin());
|
||||
addFloatArray(gv,m_thermo->speciesName(k),
|
||||
x.size(),x.begin(),"","massFraction",0.0,1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Solid1D::setJac(MultiJac* jac) {
|
||||
m_jac = jac;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
402
Cantera/src/oneD/Solid1D.h
Normal file
402
Cantera/src/oneD/Solid1D.h
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
§/**
|
||||
* @file Solid1D.h
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifndef CT_SOLID1D_H
|
||||
#define CT_SOLID1D_H
|
||||
|
||||
#include "../transport/TransportBase.h"
|
||||
#include "Domain1D.h"
|
||||
#include "../Array.h"
|
||||
#include "../sort.h"
|
||||
#include "../ThermoPhase.h"
|
||||
#include "../Kinetics.h"
|
||||
#include "../funcs.h"
|
||||
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class MultiJac;
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Class Solid1D
|
||||
//-----------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* A class for one-dimensional reacting solids with current
|
||||
* transport. This class implements the one-dimensional
|
||||
* similarity solution for a chemically-reacting, axisymmetric,
|
||||
* stagnation-point flow.
|
||||
*/
|
||||
class Solid1D : public Domain1D {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// constants
|
||||
//------------------------------------------
|
||||
|
||||
/**
|
||||
* Offsets of solution components in the solution array.
|
||||
*/
|
||||
const unsigned int c_phi_loc; // electric potential
|
||||
const unsigned int c_T_loc; // temperature
|
||||
const unsigned int c_C_loc; // concentrations
|
||||
|
||||
|
||||
//--------------------------------
|
||||
// construction and destruction
|
||||
//--------------------------------
|
||||
|
||||
// Constructor.
|
||||
Solid1D(ThermoPhase* ph = 0, int nsp = 1, int points = 1);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~Solid1D(){}
|
||||
|
||||
|
||||
/**
|
||||
* @name Problem Specification
|
||||
*/
|
||||
//@{
|
||||
|
||||
virtual void setupGrid(int n, const doublereal* z);
|
||||
|
||||
thermo_t& phase() { return *m_thermo; }
|
||||
kinetics_t& kinetics() { return *m_kin; }
|
||||
|
||||
/**
|
||||
* Set the thermo manager.
|
||||
*/
|
||||
void setThermo(thermo_t& th) {
|
||||
m_thermo = &th;
|
||||
}
|
||||
|
||||
/// set the kinetics manager
|
||||
void setKinetics(kinetics_t& kin) { m_kin = &kin; }
|
||||
|
||||
/// set the transport manager
|
||||
void setTransport(Transport& trans);
|
||||
|
||||
virtual void setState(int point, const doublereal* state) {
|
||||
setTemperature(point, state[c_T_loc]);
|
||||
setElectricPotential(point, state[c_phi_loc);
|
||||
int k;
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
setConcentration(point, k, state[c_C_loc+k]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void _getInitialSoln(doublereal* x) {
|
||||
int k, j;
|
||||
for (j = 0; j < m_points; j++) {
|
||||
x[index(c_T_loc,j)] = T_fixed(j);
|
||||
x[index(c_phi_loc,j)] = phi_fixed(j);
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
x[index(c_C_loc+k,j)] = C_fixed(k,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void _finalize(const doublereal* x) {
|
||||
int k, j;
|
||||
doublereal zz, tt;
|
||||
int nz = m_zfix.size();
|
||||
bool e = m_do_energy[0];
|
||||
for (j = 0; j < m_points; j++) {
|
||||
if (e || nz == 0)
|
||||
setTemperature(j, T(x, j));
|
||||
else {
|
||||
zz = (z(j) - z(0))/(z(m_points - 1) - z(0));
|
||||
tt = linearInterp(zz, m_zfix, m_tfix);
|
||||
setTemperature(j, tt);
|
||||
}
|
||||
setElectricPotential(j, phi(x,j));
|
||||
for (k = 0; k < m_nsp; k++) {
|
||||
setConcentration(j, k, C(x, k, j));
|
||||
}
|
||||
}
|
||||
if (e) solveEnergyEqn();
|
||||
}
|
||||
|
||||
|
||||
void setFixedTempProfile(vector_fp& zfixed, vector_fp& tfixed) {
|
||||
m_zfix = zfixed;
|
||||
m_tfix = tfixed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the temperature fixed point at grid point j, and
|
||||
* disable the energy equation so that the solution will be
|
||||
* held to this value.
|
||||
*/
|
||||
void setTemperature(int j, doublereal t) {
|
||||
m_fixedtemp[j] = t;
|
||||
m_do_energy[j] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the electric potential fixed point at grid point j, and
|
||||
* disable Gauss's equation so that the solution will be
|
||||
* held to this value.
|
||||
*/
|
||||
void setElectricPotential(int j, doublereal phi) {
|
||||
m_fixedphi[j] = phi;
|
||||
m_do_gauss[j] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mass fraction fixed point for species k at grid
|
||||
* point j, and disable the species equation so that the
|
||||
* solution will be held to this value.
|
||||
*/
|
||||
void setConcentration(int j, int k, doublereal c) {
|
||||
m_fixedc(k,j) = c;
|
||||
m_do_species[k] = true; // false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The fixed temperature value at point j.
|
||||
*/
|
||||
doublereal T_fixed(int j) const {return m_fixedtemp[j];}
|
||||
|
||||
/**
|
||||
* The fixed potential value at point j.
|
||||
*/
|
||||
doublereal phi_fixed(int j) const {return m_fixedphi[j];}
|
||||
|
||||
/**
|
||||
* The fixed mass fraction value of species k at point j.
|
||||
*/
|
||||
doublereal C_fixed(int k, int j) const {return m_fixedc(k,j);}
|
||||
|
||||
virtual string componentName(int n) const;
|
||||
|
||||
void setDielectricConstant(doublereal e) { m_eps = e; }
|
||||
doublereal dielectricConstant() { return e; }
|
||||
|
||||
/**
|
||||
* Write a Tecplot zone corresponding to the current solution.
|
||||
* May be called multiple times to generate animation.
|
||||
*/
|
||||
void outputTEC(ostream &s, const doublereal* x,
|
||||
string title, int zone);
|
||||
|
||||
virtual void showSolution(const doublereal* x);
|
||||
|
||||
virtual void save(XML_Node& o, doublereal* sol);
|
||||
|
||||
virtual void restore(XML_Node& dom, doublereal* soln);
|
||||
|
||||
// overloaded in subclasses
|
||||
virtual string solidType() { return "<none>"; }
|
||||
|
||||
void solveEnergyEqn(int j=-1) {
|
||||
if (j < 0)
|
||||
for (int i = 0; i < m_points; i++)
|
||||
m_do_energy[i] = true;
|
||||
else
|
||||
m_do_energy[j] = true;
|
||||
m_refiner->setActive(c_T_loc, true);
|
||||
needJacUpdate();
|
||||
}
|
||||
|
||||
void fixTemperature(int j=-1) {
|
||||
if (j < 0)
|
||||
for (int i = 0; i < m_points; i++) {
|
||||
m_do_energy[i] = false;
|
||||
}
|
||||
else m_do_energy[j] = false;
|
||||
m_refiner->setActive(c_T_loc, false);
|
||||
needJacUpdate();
|
||||
}
|
||||
|
||||
void solveGaussEqn(int j=-1) {
|
||||
if (j < 0)
|
||||
for (int i = 0; i < m_points; i++)
|
||||
m_do_gauss[i] = true;
|
||||
else
|
||||
m_do_gauss[j] = true;
|
||||
m_refiner->setActive(c_phi_loc, true);
|
||||
needJacUpdate();
|
||||
}
|
||||
|
||||
void fixElectricPotential(int j=-1) {
|
||||
if (j < 0)
|
||||
for (int i = 0; i < m_points; i++) {
|
||||
m_do_gauss[i] = false;
|
||||
}
|
||||
else m_do_gauss[j] = false;
|
||||
m_refiner->setActive(c_phi_loc, false);
|
||||
needJacUpdate();
|
||||
}
|
||||
|
||||
bool doSpecies(int k) { return m_do_species[k]; }
|
||||
bool doEnergy(int j) { return m_do_energy[j]; }
|
||||
bool doGauss(int j) { return m_do_gauss[j]; }
|
||||
|
||||
void solveSpecies(int k=-1) {
|
||||
if (k == -1) {
|
||||
for (int i = 0; i < m_nsp; i++)
|
||||
m_do_species[i] = true;
|
||||
}
|
||||
else m_do_species[k] = true;
|
||||
needJacUpdate();
|
||||
}
|
||||
|
||||
void fixSpecies(int k=-1) {
|
||||
if (k == -1) {
|
||||
for (int i = 0; i < m_nsp; i++)
|
||||
m_do_species[i] = false;
|
||||
}
|
||||
else m_do_species[k] = false;
|
||||
needJacUpdate();
|
||||
}
|
||||
|
||||
void resize(int points);
|
||||
|
||||
void setJac(MultiJac* jac);
|
||||
void setThermoState(const doublereal* x,int j);
|
||||
void setStateAtMidpoint(const doublereal* x,int j);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
doublereal component(const doublereal* x, int i, int j) const {
|
||||
doublereal xx = x[index(i,j)];
|
||||
return xx;
|
||||
}
|
||||
|
||||
doublereal wdot(int k, int j) const {return m_wdot(k,j);}
|
||||
|
||||
/// write the net production rates at point j into array m_wdot
|
||||
void getWdot(doublereal* x,int j) {
|
||||
setThermoState(x,j);
|
||||
m_kin->getNetProductionRates(&m_wdot(0,j));
|
||||
}
|
||||
|
||||
/**
|
||||
* update the thermodynamic properties from point
|
||||
* j0 to point j1 (inclusive), based on solution x.
|
||||
*/
|
||||
void updateThermo(const doublereal* x, int j0, int j1) {
|
||||
int j;
|
||||
for (j = j0; j <= j1; j++) {
|
||||
setThermoState(x,j);
|
||||
m_cp[j] = m_thermo->cp_mass();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------
|
||||
// solution components
|
||||
//--------------------------------
|
||||
|
||||
|
||||
doublereal T(const doublereal* x,int j) const {
|
||||
return x[index(c_T_loc, j)];
|
||||
}
|
||||
|
||||
doublereal& T(doublereal* x,int j) {return x[index(c_T_loc, j)];}
|
||||
|
||||
doublereal T_prev(int j) const {return prevSoln(c_T_loc, j);}
|
||||
|
||||
doublereal C(const doublereal* x,int k, int j) const {
|
||||
return x[index(c_C_loc + k, j)];
|
||||
}
|
||||
|
||||
doublereal& C(doublereal* x,int k, int j) {
|
||||
return x[index(c_C_loc + k, j)];
|
||||
}
|
||||
|
||||
doublereal C_prev(int k, int j) const {
|
||||
return prevSoln(c_C_loc + k, j);
|
||||
}
|
||||
|
||||
doublereal flux(int k, int j) const {
|
||||
return m_flux(k, j);
|
||||
}
|
||||
|
||||
doublereal phi(doublereal* x, j) {
|
||||
return x[index(c_phi_loc, j)];
|
||||
}
|
||||
|
||||
doublereal divHeatFlux(const doublereal* x, int j) const {
|
||||
doublereal c1 = m_tcon[j-1]*(T(x,j) - T(x,j-1));
|
||||
doublereal c2 = m_tcon[j]*(T(x,j+1) - T(x,j));
|
||||
return -2.0*(c2/(z(j+1) - z(j)) - c1/(z(j) - z(j-1)))/(z(j+1) - z(j-1));
|
||||
}
|
||||
|
||||
doublereal divDisplCurr(const doublereal* x, int j) const {
|
||||
doublereal c1 = (phi(x,j) - phi(x,j-1));
|
||||
doublereal c2 = (phi(x,j+1) - phi(x,j));
|
||||
return -2.0*m_eps*epsilon_0*
|
||||
(c2/(z(j+1) - z(j)) - c1/(z(j) - z(j-1)))/(z(j+1) - z(j-1));
|
||||
}
|
||||
|
||||
void updateDiffFluxes(const doublereal* x, int j0, int j1);
|
||||
|
||||
//---------------------------------------------------------
|
||||
//
|
||||
// member data
|
||||
//
|
||||
//---------------------------------------------------------
|
||||
|
||||
doublereal m_eps // relative dielectric constant
|
||||
|
||||
// grid parameters
|
||||
vector_fp m_dz;
|
||||
|
||||
// mixture thermo properties
|
||||
vector_fp m_cdens;
|
||||
|
||||
// transport properties
|
||||
vector_fp m_tcon;
|
||||
vector_fp m_diff;
|
||||
Array2D m_flux;
|
||||
|
||||
// production rates
|
||||
Array2D m_wdot;
|
||||
|
||||
int m_nsp;
|
||||
|
||||
thermo_t* m_thermo;
|
||||
kinetics_t* m_kin;
|
||||
Transport* m_trans;
|
||||
|
||||
MultiJac* m_jac;
|
||||
|
||||
bool m_ok;
|
||||
|
||||
// flags
|
||||
vector<bool> m_do_energy;
|
||||
vector<bool> m_do_species;
|
||||
vector<bool> m_do_gauss;
|
||||
|
||||
// fixed T and Y values
|
||||
Array2D m_fixedy;
|
||||
Array2D m_fixedphi;
|
||||
vector_fp m_fixedtemp;
|
||||
vector_fp m_zfix;
|
||||
vector_fp m_tfix;
|
||||
|
||||
private:
|
||||
|
||||
vector_fp m_cbar;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -58,10 +58,10 @@ namespace Cantera {
|
|||
m_nv = m_domain->nComponents();
|
||||
|
||||
// check consistency
|
||||
if (n != m_domain->nPoints()) return -1;
|
||||
if (n != m_domain->nPoints()) throw CanteraError("analyze","inconsistent");
|
||||
|
||||
|
||||
if (n >= m_npmax) return 0;
|
||||
if (n >= m_npmax) throw CanteraError("analyze","max points");
|
||||
|
||||
/**
|
||||
* find locations where cell size ratio is too large.
|
||||
|
|
@ -88,7 +88,7 @@ namespace Cantera {
|
|||
// }
|
||||
|
||||
for (int i = 0; i < m_nv; i++) {
|
||||
//cout << i << " " << m_nv << " " << m_active[i] << endl;
|
||||
cout << i << " " << m_nv << " " << m_active[i] << endl;
|
||||
if (m_active[i]) {
|
||||
name = m_domain->componentName(i);
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ namespace Cantera {
|
|||
m_c[name] = 1;
|
||||
if (int(m_loc.size()) + n > m_npmax) goto done;
|
||||
}
|
||||
if (r >= 0.0) {
|
||||
if (r >= -1.0) {
|
||||
m_keep[j] = 1;
|
||||
m_keep[j+1] = 1;
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ namespace Cantera {
|
|||
m_loc[j+1] = 1;
|
||||
if (int(m_loc.size()) + n > m_npmax) goto done;
|
||||
}
|
||||
if (r >= 0.0) {
|
||||
if (r >= -1.0) {
|
||||
m_keep[j+1] = 1;
|
||||
}
|
||||
//cout << "at point " << j << " slope r = "
|
||||
|
|
|
|||
84
Cantera/src/transport/SolidTransport.cpp
Normal file
84
Cantera/src/transport/SolidTransport.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
*
|
||||
* @file SolidTransport.cpp
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// copyright 2003 California Institute of Technology
|
||||
|
||||
|
||||
// turn off warnings under Windows
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "SolidTransport.h"
|
||||
|
||||
#include "utilities.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//////////////////// class SolidTransport methods //////////////
|
||||
|
||||
SolidTransport::SolidTransport() {}
|
||||
|
||||
void SolidTransport::setParameters(int n, int k, double* p) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
m_sp.push_back(k);
|
||||
m_Adiff.push_back(p[0]);
|
||||
m_Ndiff.push_back(p[1]);
|
||||
m_Ediff.push_back(p[2]);
|
||||
m_nmobile = m_sp.size();
|
||||
break;
|
||||
case 1:
|
||||
m_lam = p[0];
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* Public methods
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
|
||||
void SolidTransport::getMobilities(doublereal* mobil) {
|
||||
int k;
|
||||
getMixDiffCoeffs(mobil);
|
||||
doublereal t = m_thermo->temperature();
|
||||
int nsp = m_thermo->nSpecies();
|
||||
doublereal c1 = ElectronCharge / (Boltzmann * t);
|
||||
for (k = 0; k < nsp; k++) {
|
||||
mobil[k] *= c1 * m_thermo->charge(k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doublereal SolidTransport::thermalConductivity() {
|
||||
return m_lam;
|
||||
}
|
||||
|
||||
|
||||
void SolidTransport::getMixDiffCoeffs(doublereal* d) {
|
||||
doublereal temp = m_thermo->temperature();
|
||||
int nsp = m_thermo->nSpecies();
|
||||
int k;
|
||||
for (k = 0; k < nsp; k++) d[k] = 0.0;
|
||||
for (k = 0; k < m_nmobile; k++) {
|
||||
d[m_sp[k]] =
|
||||
m_Adiff[k] * pow(temp, m_Ndiff[k]) * exp(-m_Ediff[k]/temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Cantera/src/transport/SolidTransport.h
Normal file
81
Cantera/src/transport/SolidTransport.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
*
|
||||
* @file SolidTransport.h
|
||||
* Header file defining class SolidTransport
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2003 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_SOLIDTRAN_H
|
||||
#define CT_SOLIDTRAN_H
|
||||
|
||||
|
||||
// turn off warnings under Windows
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
// STL includes
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Cantera includes
|
||||
#include "TransportBase.h"
|
||||
#include "../DenseMatrix.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/**
|
||||
* Class SolidTransport implements transport
|
||||
* properties for solids.
|
||||
*/
|
||||
class SolidTransport : public Transport {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~SolidTransport() {}
|
||||
|
||||
virtual int model() { return cSolidTransport; }
|
||||
|
||||
virtual doublereal thermalConductivity();
|
||||
virtual void getMixDiffCoeffs(doublereal* d);
|
||||
virtual void getMobilities(doublereal* mobil);
|
||||
virtual void setParameters(int n, int k, doublereal* p);
|
||||
|
||||
friend class TransportFactory;
|
||||
|
||||
protected:
|
||||
|
||||
/// default constructor
|
||||
SolidTransport();
|
||||
|
||||
private:
|
||||
|
||||
int m_nmobile; // number of mobile species
|
||||
vector_fp m_Adiff;
|
||||
vector_fp m_Ndiff;
|
||||
vector_fp m_Ediff;
|
||||
vector_int m_sp;
|
||||
doublereal m_lam;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ namespace Cantera {
|
|||
if (units == "") return 1.0;
|
||||
doublereal f = 1.0, fctr;
|
||||
int tsize;
|
||||
string u = units, tok;
|
||||
string u = units, tok, tsub;
|
||||
int k;
|
||||
char action = '-';
|
||||
while (1 > 0) {
|
||||
|
|
@ -33,18 +33,22 @@ namespace Cantera {
|
|||
tok = u;
|
||||
tsize = tok.size();
|
||||
if (tok[tsize - 1] == '2') {
|
||||
fctr = m_u[tok.substr(0,tsize-2)];
|
||||
tsub = tok.substr(0,tsize-1);
|
||||
fctr = m_u[tsub];
|
||||
fctr *= fctr;
|
||||
}
|
||||
else if (tok[tsize - 1] == '3') {
|
||||
fctr = m_u[tok.substr(0,tsize-2)];
|
||||
tsub = tok.substr(0,tsize-1);
|
||||
fctr = m_u[tsub];
|
||||
fctr *= fctr*fctr;
|
||||
}
|
||||
else
|
||||
else {
|
||||
tsub = tok;
|
||||
fctr = m_u[tok];
|
||||
}
|
||||
|
||||
if (fctr == 0)
|
||||
throw CanteraError("toSI","unknown unit: "+tok);
|
||||
throw CanteraError("toSI","unknown unit: "+tsub);
|
||||
if (action == '-') f *= fctr;
|
||||
else if (action == '/') f /= fctr;
|
||||
if (k < 0) break;
|
||||
|
|
|
|||
|
|
@ -1,100 +1,101 @@
|
|||
<ctml>
|
||||
<elementData caseSensitive="no">
|
||||
<element name="H", atomicWt = " 1.00794"/>
|
||||
<element name="D", atomicWt = " 2.0 "/>
|
||||
<element name="Tr", atomicWt = " 3.0 "/>
|
||||
<element name="He", atomicWt = " 4.002602"/>
|
||||
<element name="Li", atomicWt = " 6.941 "/>
|
||||
<element name="Be", atomicWt = " 9.012182"/>
|
||||
<element name="B", atomicWt = " 10.811 "/>
|
||||
<element name="C", atomicWt = " 12.011 "/>
|
||||
<element name="N", atomicWt = " 14.00674"/>
|
||||
<element name="O", atomicWt = " 15.9994 "/>
|
||||
<element name="F", atomicWt = " 18.9984032"/>
|
||||
<element name="Ne", atomicWt = " 20.1797 "/>
|
||||
<element name="Na", atomicWt = " 22.98977"/>
|
||||
<element name="Mg", atomicWt = " 24.3050 "/>
|
||||
<element name="Al", atomicWt = " 26.98154"/>
|
||||
<element name="Si", atomicWt = " 28.0855 "/>
|
||||
<element name="P", atomicWt = " 30.97376"/>
|
||||
<element name="S", atomicWt = " 32.066 "/>
|
||||
<element name="Cl", atomicWt = " 35.4527 "/>
|
||||
<element name="Ar", atomicWt = " 39.948 "/>
|
||||
<element name="K", atomicWt = " 39.0983 "/>
|
||||
<element name="Ca", atomicWt = " 40.078 "/>
|
||||
<element name="Sc", atomicWt = " 44.95591"/>
|
||||
<element name="Ti", atomicWt = " 47.88 "/>
|
||||
<element name="V", atomicWt = " 50.9415 "/>
|
||||
<element name="Cr", atomicWt = " 51.9961 "/>
|
||||
<element name="Mn", atomicWt = " 54.9381 "/>
|
||||
<element name="Fe", atomicWt = " 55.847 "/>
|
||||
<element name="Co", atomicWt = " 58.9332 "/>
|
||||
<element name="Ni", atomicWt = " 58.69 "/>
|
||||
<element name="Cu", atomicWt = " 63.546 "/>
|
||||
<element name="Zn", atomicWt = " 65.39 "/>
|
||||
<element name="Ga", atomicWt = " 69.723 "/>
|
||||
<element name="Ge", atomicWt = " 72.61 "/>
|
||||
<element name="As", atomicWt = " 74.92159"/>
|
||||
<element name="Se", atomicWt = " 78.96 "/>
|
||||
<element name="Br", atomicWt = " 79.904 "/>
|
||||
<element name="Kr", atomicWt = " 83.80 "/>
|
||||
<element name="Rb", atomicWt = " 85.4678 "/>
|
||||
<element name="Sr", atomicWt = " 87.62 "/>
|
||||
<element name="Y", atomicWt = " 88.90585"/>
|
||||
<element name="Zr", atomicWt = " 91.224 "/>
|
||||
<element name="Nb", atomicWt = " 92.90638"/>
|
||||
<element name="Mo", atomicWt = " 95.94 "/>
|
||||
<element name="Tc", atomicWt = " 97.9072 "/>
|
||||
<element name="Ru", atomicWt = " 101.07 "/>
|
||||
<element name="Rh", atomicWt = " 102.9055 "/>
|
||||
<element name="Pd", atomicWt = " 106.42 "/>
|
||||
<element name="Ag", atomicWt = " 107.8682 "/>
|
||||
<element name="Cd", atomicWt = " 112.411 "/>
|
||||
<element name="In", atomicWt = " 114.82 "/>
|
||||
<element name="Sn", atomicWt = " 118.710 "/>
|
||||
<element name="Sb", atomicWt = " 121.75 "/>
|
||||
<element name="Te", atomicWt = " 127.6 "/>
|
||||
<element name="I", atomicWt = " 126.90447"/>
|
||||
<element name="Xe", atomicWt = " 131.29 "/>
|
||||
<element name="Cs", atomicWt = " 132.90543"/>
|
||||
<element name="Ba", atomicWt = " 137.327 "/>
|
||||
<element name="La", atomicWt = " 138.9055 "/>
|
||||
<element name="Ce", atomicWt = " 140.115 "/>
|
||||
<element name="Pr", atomicWt = " 140.90765"/>
|
||||
<element name="Nd", atomicWt = " 144.24 "/>
|
||||
<element name="Pm", atomicWt = " 144.9127 "/>
|
||||
<element name="Sm", atomicWt = " 150.36 "/>
|
||||
<element name="Eu", atomicWt = " 151.965 "/>
|
||||
<element name="Gd", atomicWt = " 157.25 "/>
|
||||
<element name="Tb", atomicWt = " 158.92534"/>
|
||||
<element name="Dy", atomicWt = " 162.50 "/>
|
||||
<element name="Ho", atomicWt = " 164.93032"/>
|
||||
<element name="Er", atomicWt = " 167.26 "/>
|
||||
<element name="Tm", atomicWt = " 168.93421"/>
|
||||
<element name="Yb", atomicWt = " 173.04 "/>
|
||||
<element name="Lu", atomicWt = " 174.967 "/>
|
||||
<element name="Hf", atomicWt = " 178.49 "/>
|
||||
<element name="Ta", atomicWt = " 180.9479 "/>
|
||||
<element name="W", atomicWt = " 183.85 "/>
|
||||
<element name="Re", atomicWt = " 186.207 "/>
|
||||
<element name="Os", atomicWt = " 190.2 "/>
|
||||
<element name="Ir", atomicWt = " 192.22 "/>
|
||||
<element name="Pt", atomicWt = " 195.08 "/>
|
||||
<element name="Au", atomicWt = " 196.96654"/>
|
||||
<element name="Hg", atomicWt = " 200.59 "/>
|
||||
<element name="Ti", atomicWt = " 204.3833 "/>
|
||||
<element name="Pb", atomicWt = " 207.2 "/>
|
||||
<element name="Bi", atomicWt = " 208.98037"/>
|
||||
<element name="Po", atomicWt = " 208.9824 "/>
|
||||
<element name="At", atomicWt = " 209.9871 "/>
|
||||
<element name="Rn", atomicWt = " 222.0176 "/>
|
||||
<element name="Fr", atomicWt = " 223.0197 "/>
|
||||
<element name="Ra", atomicWt = " 226.0254 "/>
|
||||
<element name="Ac", atomicWt = " 227.0279 "/>
|
||||
<element name="Th", atomicWt = " 232.0381 "/>
|
||||
<element name="Pa", atomicWt = " 231.03588"/>
|
||||
<element name="U", atomicWt = " 238.0508 "/>
|
||||
<element name="Np", atomicWt = " 237.0482 "/>
|
||||
<element name="Pu", atomicWt = " 244.0482 "/>
|
||||
<element name="H", atomicWt = "1.00794"/>
|
||||
<element name="D", atomicWt = "2.0"/>
|
||||
<element name="Tr", atomicWt = "3.0"/>
|
||||
<element name="He", atomicWt = "4.002602"/>
|
||||
<element name="Li", atomicWt = "6.941"/>
|
||||
<element name="Be", atomicWt = "9.012182"/>
|
||||
<element name="B", atomicWt = "10.811"/>
|
||||
<element name="C", atomicWt = "12.011"/>
|
||||
<element name="N", atomicWt = "14.00674"/>
|
||||
<element name="O", atomicWt = "15.9994"/>
|
||||
<element name="F", atomicWt = "18.9984032"/>
|
||||
<element name="Ne", atomicWt = "20.1797"/>
|
||||
<element name="Na", atomicWt = "22.98977"/>
|
||||
<element name="Mg", atomicWt = "24.3050"/>
|
||||
<element name="Al", atomicWt = "26.98154"/>
|
||||
<element name="Si", atomicWt = "28.0855"/>
|
||||
<element name="P", atomicWt = "30.97376"/>
|
||||
<element name="S", atomicWt = "32.066"/>
|
||||
<element name="Cl", atomicWt = "35.4527"/>
|
||||
<element name="Ar", atomicWt = "39.948"/>
|
||||
<element name="K", atomicWt = "39.0983"/>
|
||||
<element name="Ca", atomicWt = "40.078"/>
|
||||
<element name="Sc", atomicWt = "44.95591"/>
|
||||
<element name="Ti", atomicWt = "47.88"/>
|
||||
<element name="V", atomicWt = "50.9415"/>
|
||||
<element name="Cr", atomicWt = "51.9961"/>
|
||||
<element name="Mn", atomicWt = "54.9381"/>
|
||||
<element name="Fe", atomicWt = "55.847"/>
|
||||
<element name="Co", atomicWt = "58.9332"/>
|
||||
<element name="Ni", atomicWt = "58.69"/>
|
||||
<element name="Cu", atomicWt = "63.546"/>
|
||||
<element name="Zn", atomicWt = "65.39"/>
|
||||
<element name="Ga", atomicWt = "69.723"/>
|
||||
<element name="Ge", atomicWt = "72.61"/>
|
||||
<element name="As", atomicWt = "74.92159"/>
|
||||
<element name="Se", atomicWt = "78.96"/>
|
||||
<element name="Br", atomicWt = "79.904"/>
|
||||
<element name="Kr", atomicWt = "83.80"/>
|
||||
<element name="Rb", atomicWt = "85.4678"/>
|
||||
<element name="Sr", atomicWt = "87.62"/>
|
||||
<element name="Y", atomicWt = "88.90585"/>
|
||||
<element name="Zr", atomicWt = "91.224"/>
|
||||
<element name="Nb", atomicWt = "92.90638"/>
|
||||
<element name="Mo", atomicWt = "95.94 "/>
|
||||
<element name="Tc", atomicWt = "97.9072"/>
|
||||
<element name="Ru", atomicWt = "101.07"/>
|
||||
<element name="Rh", atomicWt = "102.9055"/>
|
||||
<element name="Pd", atomicWt = "106.42"/>
|
||||
<element name="Ag", atomicWt = "107.8682"/>
|
||||
<element name="Cd", atomicWt = "112.411"/>
|
||||
<element name="In", atomicWt = "114.82"/>
|
||||
<element name="Sn", atomicWt = "118.710"/>
|
||||
<element name="Sb", atomicWt = "121.75"/>
|
||||
<element name="Te", atomicWt = "127.6"/>
|
||||
<element name="I", atomicWt = " 126.90447"/>
|
||||
<element name="Xe", atomicWt = "131.29"/>
|
||||
<element name="Cs", atomicWt = "132.90543"/>
|
||||
<element name="Ba", atomicWt = "137.327"/>
|
||||
<element name="La", atomicWt = "138.9055"/>
|
||||
<element name="Ce", atomicWt = "140.115"/>
|
||||
<element name="Pr", atomicWt = "140.90765"/>
|
||||
<element name="Nd", atomicWt = "144.24"/>
|
||||
<element name="Pm", atomicWt = "144.9127"/>
|
||||
<element name="Sm", atomicWt = "150.36 "/>
|
||||
<element name="Eu", atomicWt = "151.965"/>
|
||||
<element name="Gd", atomicWt = "157.25"/>
|
||||
<element name="Tb", atomicWt = "158.92534"/>
|
||||
<element name="Dy", atomicWt = "162.50"/>
|
||||
<element name="Ho", atomicWt = "164.93032"/>
|
||||
<element name="Er", atomicWt = "167.26"/>
|
||||
<element name="Tm", atomicWt = "168.93421"/>
|
||||
<element name="Yb", atomicWt = "173.04"/>
|
||||
<element name="Lu", atomicWt = "174.967"/>
|
||||
<element name="Hf", atomicWt = "178.49"/>
|
||||
<element name="Ta", atomicWt = "180.9479"/>
|
||||
<element name="W", atomicWt = "183.85"/>
|
||||
<element name="Re", atomicWt = "186.207"/>
|
||||
<element name="Os", atomicWt = "190.2"/>
|
||||
<element name="Ir", atomicWt = "192.22"/>
|
||||
<element name="Pt", atomicWt = "195.08"/>
|
||||
<element name="Au", atomicWt = "196.96654"/>
|
||||
<element name="Hg", atomicWt = "200.59"/>
|
||||
<element name="Ti", atomicWt = "204.3833"/>
|
||||
<element name="Pb", atomicWt = "207.2"/>
|
||||
<element name="Bi", atomicWt = "208.98037"/>
|
||||
<element name="Po", atomicWt = "208.9824"/>
|
||||
<element name="At", atomicWt = "209.9871"/>
|
||||
<element name="Rn", atomicWt = "222.0176"/>
|
||||
<element name="Fr", atomicWt = "223.0197"/>
|
||||
<element name="Ra", atomicWt = "226.0254"/>
|
||||
<element name="Ac", atomicWt = "227.0279"/>
|
||||
<element name="Th", atomicWt = "232.0381"/>
|
||||
<element name="Pa", atomicWt = "231.03588"/>
|
||||
<element name="U", atomicWt = "238.0508"/>
|
||||
<element name="Np", atomicWt = "237.0482"/>
|
||||
<element name="Pu", atomicWt = "244.0482"/>
|
||||
<element name="E", atomicWt = "0.000545"/>
|
||||
</elementData>
|
||||
</ctml>
|
||||
|
|
|
|||
60
examples/cxx/flame1.cpp
Normal file
60
examples/cxx/flame1.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
#include "Cantera.h"
|
||||
#include "IdealGasMix.h"
|
||||
#include "transport.h"
|
||||
|
||||
main() {
|
||||
|
||||
// create the gas object
|
||||
|
||||
IdealGasMix gas("gri30.xml");
|
||||
doublereal temp = 500.0;
|
||||
doublereal pres = 2.0*OneAtm;
|
||||
gas.setState_TPX(temp, pres, "CH4:1.0, O2:2.0, N2:7.52");
|
||||
|
||||
// create a transport manager that implements
|
||||
// mixture-averaged transport properties
|
||||
|
||||
Transport* tr = newTransportMgr("Mix", &gas);
|
||||
|
||||
|
||||
//============= build each domain ========================
|
||||
|
||||
|
||||
//-------- step 1: create the stagnation flow -------------
|
||||
|
||||
StFlow flow(&gas);
|
||||
|
||||
// create an initial grid
|
||||
doublereal z[] = {0.0, 0.05, 0.1, 0.15, 0.2};
|
||||
flow.setupGrid(5, z);
|
||||
|
||||
// specify the objects to use to compute kinetic rates and
|
||||
// transport properties
|
||||
flow.setKinetics(&gas);
|
||||
flow.setTransport(&tr);
|
||||
|
||||
flow.setPressure(0.05*OneAtm);
|
||||
|
||||
|
||||
|
||||
//------- step 2: create the inlet -----------------------
|
||||
|
||||
Inlet1D inlet;
|
||||
inlet.setMoleFractions("CH4:1, O2:2, N2:7.52");
|
||||
inlet.setMdot(0.1);
|
||||
|
||||
|
||||
//------- step 3: create the surface ---------------------
|
||||
|
||||
Surf1D surf;
|
||||
|
||||
//=================== create the container and insert the domains =====
|
||||
|
||||
vector<Resid1D*> domains;
|
||||
domains.push_back(inlet);
|
||||
domains.push_back(flow);
|
||||
domains.push_back(surf);
|
||||
|
||||
OneDim flamesim(domains);
|
||||
}
|
||||
53
include/Interface.h
Normal file
53
include/Interface.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef CXX_INTERFACE
|
||||
#define CXX_INTERFACE
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "kernel/SurfPhase.h"
|
||||
#include "kernel/InterfaceKinetics.h"
|
||||
#include "kernel/importCTML.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class Interface :
|
||||
public SurfPhase, public InterfaceKinetics
|
||||
{
|
||||
public:
|
||||
Interface(string infile, string id, vector<ThermoPhase*> phases)
|
||||
: m_ok(false), m_r(0) {
|
||||
string path = findInputFile(infile);
|
||||
ifstream fin(path.c_str());
|
||||
if (!fin) {
|
||||
throw CanteraError("Interface","could not open "
|
||||
+path+" for reading.");
|
||||
}
|
||||
|
||||
m_r = new XML_Node("-");
|
||||
m_r->build(fin);
|
||||
|
||||
XML_Node* x = find_XML("", m_r, id, "", "");
|
||||
if (!x)
|
||||
throw CanteraError("Interface","error in find_XML");
|
||||
|
||||
importPhase(*x, this);
|
||||
phases.push_back(this);
|
||||
importKinetics(*x, phases, this);
|
||||
m_ok = true;
|
||||
}
|
||||
|
||||
|
||||
virtual ~Interface() {}
|
||||
|
||||
bool operator!() { return !m_ok;}
|
||||
bool ready() { return m_ok; }
|
||||
|
||||
protected:
|
||||
bool m_ok;
|
||||
XML_Node* m_r;
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "kernel/oneD/Sim1D.h"
|
||||
#include "kernel/oneD/OneDim.h"
|
||||
#include "kernel/oneD/Resid1D.h"
|
||||
#include "kernel/oneD/Domain1D.h"
|
||||
#include "kernel/oneD/Inlet1D.h"
|
||||
#include "kernel/oneD/MultiNewton.h"
|
||||
#include "kernel/oneD/MultiJac.h"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue