368 lines
8.8 KiB
C++
368 lines
8.8 KiB
C++
/**
|
|
* @file DustyGasTransport.cpp
|
|
* Implementation file for class DustyGasTransport
|
|
*/
|
|
|
|
/*
|
|
* Copyright 2003 California Institute of Technology
|
|
* See file License.txt for licensing information
|
|
*/
|
|
|
|
#include "cantera/thermo/ThermoPhase.h"
|
|
#include "cantera/transport/DustyGasTransport.h"
|
|
#include "cantera/base/stringUtils.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace Cantera
|
|
{
|
|
DustyGasTransport::DustyGasTransport(thermo_t* thermo) :
|
|
Transport(thermo),
|
|
m_mw(0),
|
|
m_dk(0),
|
|
m_temp(-1.0),
|
|
m_multidiff(0,0),
|
|
m_spwork(0),
|
|
m_spwork2(0),
|
|
m_gradP(0.0),
|
|
m_knudsen_ok(false),
|
|
m_bulk_ok(false),
|
|
m_porosity(0.0),
|
|
m_tortuosity(1.0),
|
|
m_pore_radius(0.0),
|
|
m_diam(0.0),
|
|
m_perm(-1.0),
|
|
m_gastran(0)
|
|
{
|
|
}
|
|
|
|
DustyGasTransport::DustyGasTransport(const DustyGasTransport& right) :
|
|
Transport(),
|
|
m_mw(0),
|
|
m_dk(0),
|
|
m_temp(-1.0),
|
|
m_multidiff(0,0),
|
|
m_spwork(0),
|
|
m_spwork2(0),
|
|
m_gradP(0.0),
|
|
m_knudsen_ok(false),
|
|
m_bulk_ok(false),
|
|
m_porosity(0.0),
|
|
m_tortuosity(1.0),
|
|
m_pore_radius(0.0),
|
|
m_diam(0.0),
|
|
m_perm(-1.0),
|
|
m_gastran(0)
|
|
{
|
|
*this = right;
|
|
}
|
|
|
|
DustyGasTransport& DustyGasTransport::operator=(const DustyGasTransport& right)
|
|
{
|
|
if (&right == this) {
|
|
return *this;
|
|
}
|
|
Transport::operator=(right);
|
|
|
|
m_mw = right.m_mw;
|
|
m_d = right.m_d;
|
|
m_x = right.m_x;
|
|
m_dk = right.m_dk;
|
|
m_temp = right.m_temp;
|
|
m_multidiff = right.m_multidiff;
|
|
m_spwork = right.m_spwork;
|
|
m_spwork2 = right.m_spwork2;
|
|
m_gradP = right.m_gradP;
|
|
m_knudsen_ok = right.m_knudsen_ok;
|
|
m_bulk_ok= right.m_bulk_ok;
|
|
m_porosity = right.m_porosity;
|
|
m_tortuosity = right.m_tortuosity;
|
|
m_pore_radius = right.m_pore_radius;
|
|
m_diam = right.m_diam;
|
|
m_perm = right.m_perm;
|
|
|
|
// Warning -> gastran may not point to the correct object
|
|
// after this copy. The routine initialize() must be called
|
|
delete m_gastran;
|
|
m_gastran = right.duplMyselfAsTransport();
|
|
|
|
|
|
return *this;
|
|
}
|
|
|
|
DustyGasTransport::~DustyGasTransport()
|
|
{
|
|
delete m_gastran;
|
|
}
|
|
|
|
Transport* DustyGasTransport::duplMyselfAsTransport() const
|
|
{
|
|
DustyGasTransport* tr = new DustyGasTransport(*this);
|
|
return dynamic_cast<Transport*>(tr);
|
|
}
|
|
|
|
void DustyGasTransport::setThermo(thermo_t& thermo)
|
|
{
|
|
|
|
Transport::setThermo(thermo);
|
|
m_gastran->setThermo(thermo);
|
|
}
|
|
|
|
void DustyGasTransport::setParameters(const int type, const int k, const doublereal* const p)
|
|
{
|
|
warn_deprecated("DustyGasTransport::setParameters");
|
|
switch (type) {
|
|
case 0:
|
|
setPorosity(p[0]);
|
|
break;
|
|
case 1:
|
|
setTortuosity(p[0]);
|
|
break;
|
|
case 2:
|
|
setMeanPoreRadius(p[0]);
|
|
break;
|
|
case 3:
|
|
setMeanParticleDiameter(p[0]);
|
|
break;
|
|
case 4:
|
|
setPermeability(p[0]);
|
|
break;
|
|
default:
|
|
throw CanteraError("DustyGasTransport::init", "unknown parameter");
|
|
}
|
|
}
|
|
|
|
void DustyGasTransport::initialize(ThermoPhase* phase, Transport* gastr)
|
|
{
|
|
|
|
// constant mixture attributes
|
|
m_thermo = phase;
|
|
m_nsp = m_thermo->nSpecies();
|
|
if (m_gastran != gastr) {
|
|
delete m_gastran;
|
|
m_gastran = gastr;
|
|
}
|
|
|
|
// make a local copy of the molecular weights
|
|
m_mw.resize(m_nsp);
|
|
copy(m_thermo->molecularWeights().begin(), m_thermo->molecularWeights().end(), m_mw.begin());
|
|
|
|
m_multidiff.resize(m_nsp, m_nsp);
|
|
m_d.resize(m_nsp, m_nsp);
|
|
m_dk.resize(m_nsp, 0.0);
|
|
|
|
m_x.resize(m_nsp, 0.0);
|
|
m_thermo->getMoleFractions(DATA_PTR(m_x));
|
|
|
|
// set flags all false
|
|
m_knudsen_ok = false;
|
|
m_bulk_ok = false;
|
|
|
|
m_spwork.resize(m_nsp);
|
|
m_spwork2.resize(m_nsp);
|
|
}
|
|
|
|
void DustyGasTransport::updateBinaryDiffCoeffs()
|
|
{
|
|
if (m_bulk_ok) {
|
|
return;
|
|
}
|
|
|
|
// get the gaseous binary diffusion coefficients
|
|
m_gastran->getBinaryDiffCoeffs(m_nsp, m_d.ptrColumn(0));
|
|
doublereal por2tort = m_porosity / m_tortuosity;
|
|
for (size_t n = 0; n < m_nsp; n++) {
|
|
for (size_t m = 0; m < m_nsp; m++) {
|
|
m_d(n,m) *= por2tort;
|
|
}
|
|
}
|
|
m_bulk_ok = true;
|
|
}
|
|
|
|
void DustyGasTransport::updateKnudsenDiffCoeffs()
|
|
{
|
|
if (m_knudsen_ok) {
|
|
return;
|
|
}
|
|
doublereal K_g = m_pore_radius * m_porosity / m_tortuosity;
|
|
const doublereal TwoThirds = 2.0/3.0;
|
|
for (size_t k = 0; k < m_nsp; k++) {
|
|
m_dk[k] = TwoThirds * K_g * sqrt((8.0 * GasConstant * m_temp)/
|
|
(Pi * m_mw[k]));
|
|
}
|
|
m_knudsen_ok = true;
|
|
}
|
|
|
|
void DustyGasTransport::eval_H_matrix()
|
|
{
|
|
updateBinaryDiffCoeffs();
|
|
updateKnudsenDiffCoeffs();
|
|
doublereal sum;
|
|
for (size_t k = 0; k < m_nsp; k++) {
|
|
|
|
// evaluate off-diagonal terms
|
|
for (size_t l = 0; l < m_nsp; l++) {
|
|
m_multidiff(k,l) = -m_x[k]/m_d(k,l);
|
|
}
|
|
|
|
// evaluate diagonal term
|
|
sum = 0.0;
|
|
for (size_t j = 0; j < m_nsp; j++) {
|
|
if (j != k) {
|
|
sum += m_x[j]/m_d(k,j);
|
|
}
|
|
}
|
|
m_multidiff(k,k) = 1.0/m_dk[k] + sum;
|
|
}
|
|
}
|
|
|
|
void DustyGasTransport::getMolarFluxes(const doublereal* const state1,
|
|
const doublereal* const state2,
|
|
const doublereal delta,
|
|
doublereal* const fluxes)
|
|
{
|
|
doublereal conc1, conc2;
|
|
|
|
// cbar will be the average concentration between the two points
|
|
doublereal* const cbar = DATA_PTR(m_spwork);
|
|
doublereal* const gradc = DATA_PTR(m_spwork2);
|
|
const doublereal t1 = state1[0];
|
|
const doublereal t2 = state2[0];
|
|
const doublereal rho1 = state1[1];
|
|
const doublereal rho2 = state2[1];
|
|
const doublereal* const y1 = state1 + 2;
|
|
const doublereal* const y2 = state2 + 2;
|
|
doublereal c1sum = 0.0, c2sum = 0.0;
|
|
|
|
for (size_t k = 0; k < m_nsp; k++) {
|
|
conc1 = rho1 * y1[k] / m_mw[k];
|
|
conc2 = rho2 * y2[k] / m_mw[k];
|
|
cbar[k] = 0.5*(conc1 + conc2);
|
|
gradc[k] = (conc2 - conc1) / delta;
|
|
c1sum += conc1;
|
|
c2sum += conc2;
|
|
}
|
|
|
|
// Calculate the pressures at p1 p2 and pbar
|
|
doublereal p1 = c1sum * GasConstant * t1;
|
|
doublereal p2 = c2sum * GasConstant * t2;
|
|
doublereal pbar = 0.5*(p1 + p2);
|
|
doublereal gradp = (p2 - p1)/delta;
|
|
doublereal tbar = 0.5*(t1 + t2);
|
|
|
|
m_thermo->setState_TPX(tbar, pbar, cbar);
|
|
|
|
updateMultiDiffCoeffs();
|
|
|
|
// Multiply m_multidiff and gradc together and store the result in fluxes[]
|
|
multiply(m_multidiff, gradc, fluxes);
|
|
|
|
divide_each(cbar, cbar + m_nsp, m_dk.begin());
|
|
|
|
// if no permeability has been specified, use result for
|
|
// close-packed spheres
|
|
double b = 0.0;
|
|
if (m_perm < 0.0) {
|
|
double p = m_porosity;
|
|
double d = m_diam;
|
|
double t = m_tortuosity;
|
|
b = p*p*p*d*d/(72.0*t*(1.0-p)*(1.0-p));
|
|
} else {
|
|
b = m_perm;
|
|
}
|
|
b *= gradp / m_gastran->viscosity();
|
|
scale(cbar, cbar + m_nsp, cbar, b);
|
|
|
|
// Multiply m_multidiff with cbar and add it to fluxes
|
|
increment(m_multidiff, cbar, fluxes);
|
|
scale(fluxes, fluxes + m_nsp, fluxes, -1.0);
|
|
}
|
|
|
|
void DustyGasTransport::updateMultiDiffCoeffs()
|
|
{
|
|
// see if temperature has changed
|
|
updateTransport_T();
|
|
|
|
// update the mole fractions
|
|
updateTransport_C();
|
|
|
|
eval_H_matrix();
|
|
|
|
// invert H
|
|
int ierr = invert(m_multidiff);
|
|
|
|
if (ierr != 0) {
|
|
throw CanteraError("DustyGasTransport::updateMultiDiffCoeffs",
|
|
"invert returned ierr = "+int2str(ierr));
|
|
}
|
|
}
|
|
|
|
void DustyGasTransport::getMultiDiffCoeffs(const size_t ld, doublereal* const d)
|
|
{
|
|
updateMultiDiffCoeffs();
|
|
for (size_t i = 0; i < m_nsp; i++) {
|
|
for (size_t j = 0; j < m_nsp; j++) {
|
|
d[ld*j + i] = m_multidiff(i,j);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DustyGasTransport::updateTransport_T()
|
|
{
|
|
if (m_temp == m_thermo->temperature()) {
|
|
return;
|
|
}
|
|
m_temp = m_thermo->temperature();
|
|
m_knudsen_ok = false;
|
|
m_bulk_ok = false;
|
|
}
|
|
|
|
void DustyGasTransport::updateTransport_C()
|
|
{
|
|
m_thermo->getMoleFractions(DATA_PTR(m_x));
|
|
|
|
// add an offset to avoid a pure species condition
|
|
// (check - this may be unnecessary)
|
|
for (size_t k = 0; k < m_nsp; k++) {
|
|
m_x[k] = std::max(Tiny, m_x[k]);
|
|
}
|
|
// diffusion coeffs depend on Pressure
|
|
m_bulk_ok = false;
|
|
}
|
|
|
|
void DustyGasTransport::setPorosity(doublereal porosity)
|
|
{
|
|
m_porosity = porosity;
|
|
m_knudsen_ok = false;
|
|
m_bulk_ok = false;
|
|
}
|
|
|
|
void DustyGasTransport::setTortuosity(doublereal tort)
|
|
{
|
|
m_tortuosity = tort;
|
|
m_knudsen_ok = false;
|
|
m_bulk_ok = false;
|
|
}
|
|
|
|
void DustyGasTransport::setMeanPoreRadius(doublereal rbar)
|
|
{
|
|
m_pore_radius = rbar;
|
|
m_knudsen_ok = false;
|
|
}
|
|
|
|
void DustyGasTransport::setMeanParticleDiameter(doublereal dbar)
|
|
{
|
|
m_diam = dbar;
|
|
}
|
|
|
|
void DustyGasTransport::setPermeability(doublereal B)
|
|
{
|
|
m_perm = B;
|
|
}
|
|
|
|
Transport& DustyGasTransport::gasTransport()
|
|
{
|
|
return *m_gastran;
|
|
}
|
|
|
|
}
|