Cantera  2.3.0
LiquidTranInteraction.cpp
Go to the documentation of this file.
1 /**
2  * @file LiquidTranInteraction.cpp
3  * Source code for liquid mixture transport property evaluations.
4  */
5 
6 // This file is part of Cantera. See License.txt in the top-level directory or
7 // at http://www.cantera.org/license.txt for license and copyright information.
8 
13 #include "cantera/base/ctml.h"
14 
15 using namespace std;
16 
17 namespace Cantera
18 {
19 
20 /**
21  * Exception thrown if an error is encountered while reading the
22  * transport database.
23  */
25 {
26 public:
27  explicit LTPmodelError(const std::string& msg)
28  : CanteraError("LTPspecies",
29  "error parsing transport data: "
30  + msg + "\n") {}
31 };
32 
33 LiquidTranInteraction::LiquidTranInteraction(TransportPropertyType tp_ind) :
34  m_model(LTI_MODEL_NOTSET),
35  m_property(tp_ind)
36 {
37 }
38 
39 LiquidTranInteraction::~LiquidTranInteraction()
40 {
41  for (size_t k = 0; k < m_Aij.size(); k++) {
42  delete m_Aij[k];
43  }
44  for (size_t k = 0; k < m_Bij.size(); k++) {
45  delete m_Bij[k];
46  }
47  for (size_t k = 0; k < m_Hij.size(); k++) {
48  delete m_Hij[k];
49  }
50  for (size_t k = 0; k < m_Sij.size(); k++) {
51  delete m_Sij[k];
52  }
53 }
54 
55 void LiquidTranInteraction::init(const XML_Node& compModelNode,
56  thermo_t* thermo)
57 {
58  m_thermo = thermo;
59  size_t nsp = thermo->nSpecies();
60  m_Dij.resize(nsp, nsp, 0.0);
61  m_Eij.resize(nsp, nsp, 0.0);
62 
63  for (size_t iChild = 0; iChild < compModelNode.nChildren(); iChild++) {
64  XML_Node& xmlChild = compModelNode.child(iChild);
65  std::string nodeName = xmlChild.name();
66  if (!ba::iequals(nodeName, "interaction")) {
67  throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
68  "expected <interaction> element and got <" + nodeName + ">");
69  }
70  string speciesA = xmlChild.attrib("speciesA");
71  string speciesB = xmlChild.attrib("speciesB");
72  size_t iSpecies = m_thermo->speciesIndex(speciesA);
73  if (iSpecies == npos) {
74  throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
75  "Unknown species " + speciesA);
76  }
77  size_t jSpecies = m_thermo->speciesIndex(speciesB);
78  if (jSpecies == npos) {
79  throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
80  "Unknown species " + speciesB);
81  }
82 
83  if (xmlChild.hasChild("Eij")) {
84  m_Eij(iSpecies,jSpecies) = getFloat(xmlChild, "Eij", "actEnergy");
85  m_Eij(iSpecies,jSpecies) /= GasConstant;
86  m_Eij(jSpecies,iSpecies) = m_Eij(iSpecies,jSpecies);
87  }
88 
89  if (xmlChild.hasChild("Aij")) {
90  vector_fp poly;
91  getFloatArray(xmlChild, poly, true, "toSI", "Aij");
92  while (m_Aij.size()<poly.size()) {
93  DenseMatrix* aTemp = new DenseMatrix();
94  aTemp->resize(nsp, nsp, 0.0);
95  m_Aij.push_back(aTemp);
96  }
97  for (int i = 0; i < (int)poly.size(); i++) {
98  (*m_Aij[i])(iSpecies,jSpecies) = poly[i];
99  }
100  }
101 
102  if (xmlChild.hasChild("Bij")) {
103  vector_fp poly;
104  getFloatArray(xmlChild, poly, true, "toSI", "Bij");
105  while (m_Bij.size() < poly.size()) {
106  DenseMatrix* bTemp = new DenseMatrix();
107  bTemp->resize(nsp, nsp, 0.0);
108  m_Bij.push_back(bTemp);
109  }
110  for (size_t i=0; i<poly.size(); i++) {
111  (*m_Bij[i])(iSpecies,jSpecies) = poly[i];
112  }
113  }
114 
115  if (xmlChild.hasChild("Hij")) {
116  vector_fp poly;
117  getFloatArray(xmlChild, poly, true, "actEnergy", "Hij");
118  while (m_Hij.size()<poly.size()) {
119  DenseMatrix* hTemp = new DenseMatrix();
120  hTemp->resize(nsp, nsp, 0.0);
121  m_Hij.push_back(hTemp);
122  }
123  for (size_t i=0; i<poly.size(); i++) {
124  (*m_Hij[i])(iSpecies,jSpecies) = poly[i];
125  (*m_Hij[i])(iSpecies,jSpecies) /= GasConstant;
126  }
127  }
128 
129  if (xmlChild.hasChild("Sij")) {
130  vector_fp poly;
131  getFloatArray(xmlChild, poly, true, "actEnergy", "Sij");
132  while (m_Sij.size()<poly.size()) {
133  DenseMatrix* sTemp = new DenseMatrix();
134  sTemp->resize(nsp, nsp, 0.0);
135  m_Sij.push_back(sTemp);
136  }
137  for (size_t i=0; i<poly.size(); i++) {
138  (*m_Sij[i])(iSpecies,jSpecies) = poly[i];
139  (*m_Sij[i])(iSpecies,jSpecies) /= GasConstant;
140  }
141  }
142 
143  if (xmlChild.hasChild("Dij")) {
144  m_Dij(iSpecies,jSpecies) = getFloat(xmlChild, "Dij", "toSI");
145  m_Dij(jSpecies,iSpecies) = m_Dij(iSpecies,jSpecies);
146  }
147  }
148 }
149 
150 LTI_Solvent::LTI_Solvent(TransportPropertyType tp_ind) :
151  LiquidTranInteraction(tp_ind)
152 {
153  m_model = LTI_MODEL_SOLVENT;
154 }
155 
156 doublereal LTI_Solvent::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
157 {
158  size_t nsp = m_thermo->nSpecies();
159  doublereal temp = m_thermo->temperature();
160  vector_fp molefracs(nsp);
161  m_thermo->getMoleFractions(&molefracs[0]);
162  doublereal value = 0.0;
163 
164  //if weightings are specified, use those
165  if (speciesWeight) {
166  for (size_t k = 0; k < nsp; k++) {
167  // should be: molefracs[k] = molefracs[k]*speciesWeight[k]; for consistency, but weight(solvent)=1?
168  }
169  } else {
170  throw CanteraError("LTI_Solvent::getMixTransProp","You should be specifying the speciesWeight");
171  }
172 
173  for (size_t i = 0; i < nsp; i++) {
174  //presume that the weighting is set to 1.0 for solvent and 0.0 for everything else.
175  value += speciesValues[i] * speciesWeight[i];
176  if (i == 0) {
177  AssertTrace(speciesWeight[i] == 1.0);
178  } else {
179  AssertTrace(speciesWeight[i] == 0.0);
180  }
181  for (size_t j = 0; j < nsp; j++) {
182  for (size_t k = 0; k < m_Aij.size(); k++) {
183  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
184  }
185  for (size_t k = 0; k < m_Bij.size(); k++) {
186  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
187  }
188  }
189  }
190  return value;
191 }
192 
193 doublereal LTI_Solvent::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
194 {
195  size_t nsp = m_thermo->nSpecies();
196  doublereal temp = m_thermo->temperature();
197  vector_fp molefracs(nsp);
198  m_thermo->getMoleFractions(&molefracs[0]);
199  doublereal value = 0.0;
200 
201  for (size_t k = 0; k < nsp; k++) {
202  // should be: molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight(); for consistency, but weight(solvent)=1?
203  }
204 
205  for (size_t i = 0; i < nsp; i++) {
206  //presume that the weighting is set to 1.0 for solvent and 0.0 for everything else.
207  value += LTPptrs[i]->getSpeciesTransProp() * LTPptrs[i]->getMixWeight();
208  for (size_t j = 0; j < nsp; j++) {
209  for (size_t k = 0; k < m_Aij.size(); k++) {
210  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
211  }
212  for (size_t k = 0; k < m_Bij.size(); k++) {
213  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
214  }
215  }
216  }
217  return value;
218 }
219 
220 void LTI_Solvent::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
221 {
222  mat = (*m_Aij[0]);
223 }
224 
225 doublereal LTI_MoleFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
226 {
227  size_t nsp = m_thermo->nSpecies();
228  doublereal temp = m_thermo->temperature();
229  vector_fp molefracs(nsp);
230  m_thermo->getMoleFractions(&molefracs[0]);
231  doublereal value = 0;
232 
233  //if weightings are specified, use those
234  if (speciesWeight) {
235  for (size_t k = 0; k < nsp; k++) {
236  molefracs[k] = molefracs[k]*speciesWeight[k];
237  }
238  } else {
239  throw CanteraError("LTI_MoleFracs::getMixTransProp","You should be specifying the speciesWeight");
240  }
241 
242  for (size_t i = 0; i < nsp; i++) {
243  value += speciesValues[i] * molefracs[i];
244  for (size_t j = 0; j < nsp; j++) {
245  for (size_t k = 0; k < m_Aij.size(); k++) {
246  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
247  }
248  for (size_t k = 0; k < m_Bij.size(); k++) {
249  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
250  }
251  }
252  }
253  return value;
254 }
255 
256 doublereal LTI_MoleFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
257 {
258  size_t nsp = m_thermo->nSpecies();
259  doublereal temp = m_thermo->temperature();
260  vector_fp molefracs(nsp);
261  m_thermo->getMoleFractions(&molefracs[0]);
262  doublereal value = 0;
263 
264  for (size_t k = 0; k < nsp; k++) {
265  molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
266  }
267 
268  for (size_t i = 0; i < nsp; i++) {
269  value += LTPptrs[i]->getSpeciesTransProp() * molefracs[i];
270  for (size_t j = 0; j < nsp; j++) {
271  for (size_t k = 0; k < m_Aij.size(); k++) {
272  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
273  }
274  for (size_t k = 0; k < m_Bij.size(); k++) {
275  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
276  }
277  }
278  }
279  return value;
280 }
281 
282 doublereal LTI_MassFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
283 {
284  size_t nsp = m_thermo->nSpecies();
285  doublereal temp = m_thermo->temperature();
286  vector_fp massfracs(nsp);
287  m_thermo->getMassFractions(&massfracs[0]);
288  doublereal value = 0;
289 
290  //if weightings are specified, use those
291  if (speciesWeight) {
292  for (size_t k = 0; k < nsp; k++) {
293  massfracs[k] = massfracs[k]*speciesWeight[k];
294  }
295  } else {
296  throw CanteraError("LTI_MassFracs::getMixTransProp","You should be specifying the speciesWeight");
297  }
298 
299  for (size_t i = 0; i < nsp; i++) {
300  value += speciesValues[i] * massfracs[i];
301  for (size_t j = 0; j < nsp; j++) {
302  for (size_t k = 0; k < m_Aij.size(); k++) {
303  value += massfracs[i]*massfracs[j]*(*m_Aij[k])(i,j)*pow(massfracs[i], (int) k);
304  }
305  for (size_t k = 0; k < m_Bij.size(); k++) {
306  value += massfracs[i]*massfracs[j]*(*m_Bij[k])(i,j)*temp*pow(massfracs[i], (int) k);
307  }
308  }
309  }
310 
311  return value;
312 }
313 
314 doublereal LTI_MassFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
315 {
316  size_t nsp = m_thermo->nSpecies();
317  doublereal temp = m_thermo->temperature();
318  vector_fp massfracs(nsp);
319  m_thermo->getMassFractions(&massfracs[0]);
320  doublereal value = 0;
321 
322  for (size_t k = 0; k < nsp; k++) {
323  massfracs[k] = massfracs[k]*LTPptrs[k]->getMixWeight();
324  }
325 
326  for (size_t i = 0; i < nsp; i++) {
327  value += LTPptrs[i]->getSpeciesTransProp() * massfracs[i];
328  for (size_t j = 0; j < nsp; j++) {
329  for (size_t k = 0; k < m_Aij.size(); k++) {
330  value += massfracs[i]*massfracs[j]*(*m_Aij[k])(i,j)*pow(massfracs[i], (int) k);
331  }
332  for (size_t k = 0; k < m_Bij.size(); k++) {
333  value += massfracs[i]*massfracs[j]*(*m_Bij[k])(i,j)*temp*pow(massfracs[i], (int) k);
334  }
335  }
336  }
337  return value;
338 }
339 
340 doublereal LTI_Log_MoleFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
341 {
342  size_t nsp = m_thermo->nSpecies();
343  doublereal temp = m_thermo->temperature();
344  vector_fp molefracs(nsp);
345  m_thermo->getMoleFractions(&molefracs[0]);
346  doublereal value = 0;
347 
348  //if weightings are specified, use those
349  if (speciesWeight) {
350  for (size_t k = 0; k < nsp; k++) {
351  molefracs[k] = molefracs[k]*speciesWeight[k];
352  }
353  } else {
354  throw CanteraError("LTI_Log_MoleFracs::getMixTransProp","You probably should have a speciesWeight when you call getMixTransProp to convert ion mole fractions to molecular mole fractions");
355  }
356 
357  for (size_t i = 0; i < nsp; i++) {
358  value += log(speciesValues[i]) * molefracs[i];
359  for (size_t j = 0; j < nsp; j++) {
360  for (size_t k = 0; k < m_Hij.size(); k++) {
361  value += molefracs[i]*molefracs[j]*(*m_Hij[k])(i,j)/temp*pow(molefracs[i], (int) k);
362  }
363  for (size_t k = 0; k < m_Sij.size(); k++) {
364  value -= molefracs[i]*molefracs[j]*(*m_Sij[k])(i,j)*pow(molefracs[i], (int) k);
365  }
366  }
367  }
368  return exp(value);
369 }
370 
371 doublereal LTI_Log_MoleFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
372 {
373  size_t nsp = m_thermo->nSpecies();
374  doublereal temp = m_thermo->temperature();
375  vector_fp molefracs(nsp);
376  m_thermo->getMoleFractions(&molefracs[0]);
377  doublereal value = 0;
378 
379  //if weightings are specified, use those
380  for (size_t k = 0; k < nsp; k++) {
381  molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
382  }
383 
384  for (size_t i = 0; i < nsp; i++) {
385  value += log(LTPptrs[i]->getSpeciesTransProp()) * molefracs[i];
386  for (size_t j = 0; j < nsp; j++) {
387  for (size_t k = 0; k < m_Hij.size(); k++) {
388  value += molefracs[i]*molefracs[j]*(*m_Hij[k])(i,j)/temp*pow(molefracs[i], (int) k);
389  }
390  for (size_t k = 0; k < m_Sij.size(); k++) {
391  value -= molefracs[i]*molefracs[j]*(*m_Sij[k])(i,j)*pow(molefracs[i], (int) k);
392  }
393  }
394  }
395  return exp(value);
396 }
397 
398 void LTI_Pairwise_Interaction::setParameters(LiquidTransportParams& trParam)
399 {
400  size_t nsp = m_thermo->nSpecies();
401  m_diagonals.resize(nsp, 0);
402 
403  for (size_t k = 0; k < nsp; k++) {
404  LiquidTransportData& ltd = trParam.LTData[k];
405  if (ltd.speciesDiffusivity) {
406  m_diagonals[k] = ltd.speciesDiffusivity;
407  }
408  }
409 }
410 
411 doublereal LTI_Pairwise_Interaction::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
412 {
413  throw LTPmodelError("Calling LTI_Pairwise_Interaction::getMixTransProp does not make sense.");
414 }
415 
416 doublereal LTI_Pairwise_Interaction::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
417 {
418  throw LTPmodelError("Calling LTI_Pairwise_Interaction::getMixTransProp does not make sense.");
419 }
420 
421 void LTI_Pairwise_Interaction::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
422 {
423  size_t nsp = m_thermo->nSpecies();
424  doublereal temp = m_thermo->temperature();
425  vector_fp molefracs(nsp);
426  m_thermo->getMoleFractions(&molefracs[0]);
427 
428  mat.resize(nsp, nsp, 0.0);
429  for (size_t i = 0; i < nsp; i++) {
430  for (size_t j = 0; j < i; j++) {
431  mat(i,j) = mat(j,i) = exp(m_Eij(i,j) / temp) / m_Dij(i,j);
432  }
433  }
434 
435  for (size_t i = 0; i < nsp; i++) {
436  if (mat(i,i) == 0.0 && m_diagonals[i]) {
437  mat(i,i) = 1.0 / m_diagonals[i]->getSpeciesTransProp();
438  }
439  }
440 }
441 
442 void LTI_StefanMaxwell_PPN::setParameters(LiquidTransportParams& trParam)
443 {
444  size_t nsp = m_thermo->nSpecies();
445  m_ionCondMix = 0;
446  m_ionCondMixModel = trParam.ionConductivity;
447  m_ionCondSpecies.resize(nsp,0);
448  m_mobRatMix.resize(nsp,nsp,0.0);
449  m_mobRatMixModel.resize(nsp*nsp);
450  m_mobRatSpecies.resize(nsp*nsp);
451  m_selfDiffMix.resize(nsp,0.0);
452  m_selfDiffMixModel.resize(nsp);
453  m_selfDiffSpecies.resize(nsp);
454 
455  for (size_t k = 0; k < nsp*nsp; k++) {
456  m_mobRatMixModel[k] = trParam.mobilityRatio[k];
457  m_mobRatSpecies[k].resize(nsp,0);
458  }
459  for (size_t k = 0; k < nsp; k++) {
460  m_selfDiffMixModel[k] = trParam.selfDiffusion[k];
461  m_selfDiffSpecies[k].resize(nsp,0);
462  }
463 
464  for (size_t k = 0; k < nsp; k++) {
465  LiquidTransportData& ltd = trParam.LTData[k];
466  m_ionCondSpecies[k] = ltd.ionConductivity;
467  for (size_t j = 0; j < nsp*nsp; j++) {
468  m_mobRatSpecies[j][k] = ltd.mobilityRatio[j];
469  }
470  for (size_t j = 0; j < nsp; j++) {
471  m_selfDiffSpecies[j][k] = ltd.selfDiffusion[j];
472  }
473  }
474 }
475 
476 doublereal LTI_StefanMaxwell_PPN::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
477 {
478  throw LTPmodelError("Calling LTI_StefanMaxwell_PPN::getMixTransProp does not make sense.");
479 }
480 
481 doublereal LTI_StefanMaxwell_PPN::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
482 {
483  throw LTPmodelError("Calling LTI_StefanMaxwell_PPN::getMixTransProp does not make sense.");
484 }
485 
486 void LTI_StefanMaxwell_PPN::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
487 {
488  IonsFromNeutralVPSSTP* ions_thermo = dynamic_cast<IonsFromNeutralVPSSTP*>(m_thermo);
489  size_t nsp = m_thermo->nSpecies();
490  if (nsp != 3) {
491  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Function may only be called with a 3-ion system");
492  }
493  doublereal temp = m_thermo->temperature();
494  vector_fp molefracs(nsp);
495  m_thermo->getMoleFractions(&molefracs[0]);
496  vector_fp neut_molefracs;
497  ions_thermo->getNeutralMolecMoleFractions(neut_molefracs);
498  vector<size_t> cation;
499  vector<size_t> anion;
500  ions_thermo->getCationList(cation);
501  ions_thermo->getAnionList(anion);
502 
503  // Reaction Coeffs and Charges
504  vector_fp viS(6);
505  vector_fp charges(3);
506  std::vector<size_t> neutMolIndex(3);
507  ions_thermo->getDissociationCoeffs(viS,charges,neutMolIndex);
508 
509  if (anion.size() != 1) {
510  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Must have one anion only for StefanMaxwell_PPN");
511  }
512  if (cation.size() != 2) {
513  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Must have two cations of equal charge for StefanMaxwell_PPN");
514  }
515  if (charges[cation[0]] != charges[cation[1]]) {
516  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Cations must be of equal charge for StefanMaxwell_PPN");
517  }
518 
519  m_ionCondMix = m_ionCondMixModel->getMixTransProp(m_ionCondSpecies);
520  MargulesVPSSTP* marg_thermo = dynamic_cast<MargulesVPSSTP*>(ions_thermo->neutralMoleculePhase_);
521  doublereal vol = m_thermo->molarVolume();
522 
523  size_t k = 0;
524  for (size_t j = 0; j < nsp; j++) {
525  for (size_t i = 0; i < nsp; i++) {
526  if (m_mobRatMixModel[k]) {
527  m_mobRatMix(i,j) = m_mobRatMixModel[k]->getMixTransProp(m_mobRatSpecies[k]);
528  if (m_mobRatMix(i,j) > 0.0) {
529  m_mobRatMix(j,i) = 1.0/m_mobRatMix(i,j);
530  }
531  }
532  k++;
533  }
534  }
535 
536  for (k = 0; k < nsp; k++) {
537  m_selfDiffMix[k] = m_selfDiffMixModel[k]->getMixTransProp(m_selfDiffSpecies[k]);
538  }
539 
540  double vP = max(viS[cation[0]],viS[cation[1]]);
541  double vM = viS[anion[0]];
542  double zP = charges[cation[0]];
543  double zM = charges[anion[0]];
544  vector_fp dlnActCoeffdlnN_diag(neut_molefracs.size(),0.0);
545  marg_thermo->getdlnActCoeffdlnN_diag(&dlnActCoeffdlnN_diag[0]);
546 
547  double xA = neut_molefracs[neutMolIndex[cation[0]]];
548  double xB = neut_molefracs[neutMolIndex[cation[1]]];
549  double eps = (1-m_mobRatMix(cation[1],cation[0]))/(xA+xB*m_mobRatMix(cation[1],cation[0]));
550  double inv_vP_vM_MutualDiff = (xA*(1-xB+dlnActCoeffdlnN_diag[neutMolIndex[cation[1]]])/m_selfDiffMix[cation[1]]+xB*(1-xA+dlnActCoeffdlnN_diag[neutMolIndex[cation[0]]])/m_selfDiffMix[cation[0]]);
551 
552  mat.resize(nsp, nsp, 0.0);
553  mat(cation[0],cation[1]) = mat(cation[1],cation[0]) = (1+vM/vP)*(1+eps*xB)*(1-eps*xA)*inv_vP_vM_MutualDiff-zP*zP*Faraday*Faraday/GasConstant/temp/m_ionCondMix/vol;
554  mat(cation[0],anion[0]) = mat(anion[0],cation[0]) = (1+vP/vM)*(-eps*xB*(1-eps*xA)*inv_vP_vM_MutualDiff)-zP*zM*Faraday*Faraday/GasConstant/temp/m_ionCondMix/vol;
555  mat(cation[1],anion[0]) = mat(anion[0],cation[1]) = (1+vP/vM)*(eps*xA*(1+eps*xB)*inv_vP_vM_MutualDiff)-zP*zM*Faraday*Faraday/GasConstant/temp/m_ionCondMix/vol;
556 }
557 
558 doublereal LTI_StokesEinstein::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
559 {
560  throw LTPmodelError("Calling LTI_StokesEinstein::getMixTransProp does not make sense.");
561 }
562 
563 doublereal LTI_StokesEinstein::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
564 {
565  throw LTPmodelError("Calling LTI_StokesEinstein::getMixTransProp does not make sense.");
566 }
567 
568 void LTI_StokesEinstein::setParameters(LiquidTransportParams& trParam)
569 {
570  size_t nsp = m_thermo->nSpecies();
571  m_viscosity.resize(nsp, 0);
572  m_hydroRadius.resize(nsp, 0);
573  for (size_t k = 0; k < nsp; k++) {
574  LiquidTransportData& ltd = trParam.LTData[k];
575  m_viscosity[k] = ltd.viscosity;
576  m_hydroRadius[k] = ltd.hydroRadius;
577  }
578 }
579 
580 void LTI_StokesEinstein::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
581 {
582  size_t nsp = m_thermo->nSpecies();
583  doublereal temp = m_thermo->temperature();
584  vector_fp viscSpec(nsp);
585  vector_fp radiusSpec(nsp);
586 
587  for (size_t k = 0; k < nsp; k++) {
588  viscSpec[k] = m_viscosity[k]->getSpeciesTransProp();
589  radiusSpec[k] = m_hydroRadius[k]->getSpeciesTransProp();
590  }
591 
592  mat.resize(nsp,nsp, 0.0);
593  for (size_t i = 0; i < nsp; i++) {
594  for (size_t j = 0; j < nsp; j++) {
595  mat(i,j) = (6.0 * Pi * radiusSpec[i] * viscSpec[j]) / GasConstant / temp;
596  }
597  }
598 }
599 
600 doublereal LTI_MoleFracs_ExpT::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
601 {
602  size_t nsp = m_thermo->nSpecies();
603  doublereal temp = m_thermo->temperature();
604  vector_fp molefracs(nsp);
605  m_thermo->getMoleFractions(&molefracs[0]);
606  doublereal value = 0;
607 
608  //if weightings are specified, use those
609  if (speciesWeight) {
610  for (size_t k = 0; k < nsp; k++) {
611  molefracs[k] = molefracs[k]*speciesWeight[k];
612  }
613  } else {
614  throw CanteraError("LTI_MoleFracs_ExpT::getMixTransProp","You should be specifying the speciesWeight");
615  }
616 
617  for (size_t i = 0; i < nsp; i++) {
618  value += speciesValues[i] * molefracs[i];
619  for (size_t j = 0; j < nsp; j++) {
620  for (size_t k = 0; k < m_Aij.size(); k++) {
621  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k)*exp((*m_Bij[k])(i,j)*temp);
622  }
623  }
624  }
625  return value;
626 }
627 
628 doublereal LTI_MoleFracs_ExpT::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
629 {
630  size_t nsp = m_thermo->nSpecies();
631  doublereal temp = m_thermo->temperature();
632  vector_fp molefracs(nsp);
633  m_thermo->getMoleFractions(&molefracs[0]);
634  doublereal value = 0;
635 
636  for (size_t k = 0; k < nsp; k++) {
637  molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
638  }
639 
640  for (size_t i = 0; i < nsp; i++) {
641  value += LTPptrs[i]->getSpeciesTransProp() * molefracs[i];
642  for (size_t j = 0; j < nsp; j++) {
643  for (size_t k = 0; k < m_Aij.size(); k++) {
644  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k)*exp((*m_Bij[k])(i,j)*temp);
645  }
646  }
647  }
648  return value;
649 }
650 
651 } //namespace Cantera
size_t getFloatArray(const XML_Node &node, vector_fp &v, const bool convert, const std::string &unitsString, const std::string &nodeName)
This function reads the current node or a child node of the current node with the default name...
Definition: ctml.cpp:299
doublereal molarVolume() const
Molar volume (m^3/kmol).
Definition: Phase.cpp:676
thermo_t * m_thermo
pointer to thermo object to get current temperature
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Return the mixture transport property value.
TransportPropertyType
Enumeration of the types of transport properties that can be handled by the variables in the various ...
Definition: LTPspecies.h:34
LiquidTranMixingModel m_model
Model for species interaction effects. Takes enum LiquidTranMixingModel.
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
std::string name() const
Returns the name of the XML node.
Definition: xml.h:370
std::vector< LiquidTranInteraction * > mobilityRatio
Vector of pointer to the LiquidTranInteraction object which handles the calculation of the mobility r...
void getMassFractions(doublereal *const y) const
Get the species mass fractions.
Definition: Phase.cpp:584
(see Thermodynamic Properties and class MargulesVPSSTP).
std::vector< DenseMatrix * > m_Hij
Matrix of interaction coefficients for polynomial in molefraction*weight of speciesA (in energy units...
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
size_t speciesIndex(const std::string &name) const
Returns the index of a species named &#39;name&#39; within the Phase object.
Definition: Phase.cpp:251
Header for intermediate ThermoPhase object for phases which consist of ions whose thermodynamics is c...
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Return the mixture transport property value.
std::vector< DenseMatrix * > m_Bij
Matrix of interaction coefficients for polynomial in molefraction*weight of speciesA (linear temperat...
std::vector< DenseMatrix * > m_Aij
Matrix of interaction coefficients for polynomial in molefraction*weight of speciesA (no temperature ...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:262
STL namespace.
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of log species mole number derivatives of the log activity coefficients.
const doublereal Pi
Pi.
Definition: ct_defs.h:51
virtual doublereal getMixTransProp(doublereal *speciesValues, doublereal *weightSpecies=0)
Return the mixture transport property value.
void getMatrixTransProp(DenseMatrix &mat, doublereal *speciesValues=0)
Return the matrix of binary interaction parameters.
void getMatrixTransProp(DenseMatrix &mat, doublereal *speciesValues=0)
Return the matrix of binary interaction parameters.
std::vector< LiquidTransportData > LTData
Species transport parameters.
void getAnionList(std::vector< size_t > &anion) const
Get the list of anions in this object.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:93
Class LiquidTransportParams holds transport model parameters relevant to transport in mixtures...
std::vector< LiquidTranInteraction * > selfDiffusion
Vector of pointer to the LiquidTranInteraction object which handles the calculation of each species&#39; ...
Header file defining class LiquidTransportParams.
LiquidTranInteraction * ionConductivity
Object that specifies the ionic Conductivity of the mixture.
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the matrix.
Definition: DenseMatrix.cpp:69
DenseMatrix m_Dij
Matrix of interactions.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
Exception thrown if an error is encountered while reading the transport database. ...
std::vector< DenseMatrix * > m_Sij
Matrix of interaction coefficients for polynomial in molefraction*weight of speciesA (in entropy unit...
void getNeutralMolecMoleFractions(vector_fp &neutralMoleculeMoleFractions) const
Return the current value of the neutral mole fraction vector.
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:542
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:536
XML_Node & child(const size_t n) const
Return a changeable reference to the n&#39;th child of the current node.
Definition: xml.cpp:546
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:239
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:500
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:157
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Return the mixture transport property value.
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:64
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Return the mixture transport property value.
Contains declarations for string manipulation functions within Cantera.
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
Definition: ctml.cpp:178
MargulesVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Margules approximation for th...
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Return the mixture transport property value.
void getCationList(std::vector< size_t > &cation) const
Get the list of cations in this object.
virtual void init(const XML_Node &compModelNode=XML_Node(), thermo_t *thermo=0)
initialize LiquidTranInteraction objects with thermo and XML node
void getDissociationCoeffs(vector_fp &fm_neutralMolec_ions, vector_fp &charges, std::vector< size_t > &neutMolIndex) const
Get the Salt Dissociation Coefficients.
Namespace for the Cantera kernel.
Definition: application.cpp:29
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Return the mixture transport property value.
ThermoPhase * neutralMoleculePhase_
This is a pointer to the neutral Molecule Phase.
DenseMatrix m_Eij
Matrix of interactions (in energy units, 1/RT temperature dependence)
Base class to handle transport property evaluation in a mixture.
size_t nChildren(bool discardComments=false) const
Return the number of children.
Definition: xml.cpp:556
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
Definition: DenseMatrix.h:72