Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
10 #include "cantera/base/ctml.h"
11 
12 using namespace std;
13 
14 namespace Cantera
15 {
16 /**
17  * Exception thrown if an error is encountered while reading the
18  * transport database.
19  */
20 class LTPError : public CanteraError
21 {
22 public:
23  explicit LTPError(const std::string& msg)
24  : CanteraError("LTPspecies",
25  "error parsing transport data: "
26  + msg + "\n") {}
27 };
28 
29 /**
30  * Exception thrown if an error is encountered while reading the
31  * transport database.
32  */
34 {
35 public:
36  explicit LTPmodelError(const std::string& msg)
37  : CanteraError("LTPspecies",
38  "error parsing transport data: "
39  + msg + "\n") {}
40 };
41 
42 LiquidTranInteraction::LiquidTranInteraction(TransportPropertyType tp_ind) :
43  m_model(LTI_MODEL_NOTSET),
44  m_property(tp_ind)
45 {
46 }
47 
48 LiquidTranInteraction::~LiquidTranInteraction()
49 {
50  size_t kmax = m_Aij.size();
51  for (size_t k = 0; k < kmax; k++) {
52  delete m_Aij[k];
53  }
54  kmax = m_Bij.size();
55  for (size_t k = 0; k < kmax; k++) {
56  delete m_Bij[k];
57  }
58  kmax = m_Hij.size();
59  for (size_t k = 0; k < kmax; k++) {
60  delete m_Hij[k];
61  }
62  kmax = m_Sij.size();
63  for (size_t k = 0; k < kmax; k++) {
64  delete m_Sij[k];
65  }
66 }
67 
68 void LiquidTranInteraction::init(const XML_Node& compModelNode,
69  thermo_t* thermo)
70 {
71  m_thermo = thermo;
72 
73  size_t nsp = thermo->nSpecies();
74  m_Dij.resize(nsp, nsp, 0.0);
75  m_Eij.resize(nsp, nsp, 0.0);
76 
77  std::string speciesA;
78  std::string speciesB;
79 
80  size_t num = compModelNode.nChildren();
81  for (size_t iChild = 0; iChild < num; iChild++) {
82  XML_Node& xmlChild = compModelNode.child(iChild);
83  std::string nodeName = lowercase(xmlChild.name());
84  if (nodeName != "interaction") {
85  throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
86  "expected <interaction> element and got <" + nodeName + ">");
87  }
88  speciesA = xmlChild.attrib("speciesA");
89  speciesB = xmlChild.attrib("speciesB");
90  size_t iSpecies = m_thermo->speciesIndex(speciesA);
91  if (iSpecies == npos) {
92  throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
93  "Unknown species " + speciesA);
94  }
95  size_t jSpecies = m_thermo->speciesIndex(speciesB);
96  if (jSpecies == npos) {
97  throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
98  "Unknown species " + speciesB);
99  }
100 
101  if (xmlChild.hasChild("Eij")) {
102  m_Eij(iSpecies,jSpecies) = getFloat(xmlChild, "Eij", "actEnergy");
103  m_Eij(iSpecies,jSpecies) /= GasConstant;
104  m_Eij(jSpecies,iSpecies) = m_Eij(iSpecies,jSpecies) ;
105  }
106 
107  if (xmlChild.hasChild("Aij")) {
108  vector_fp poly;
109  getFloatArray(xmlChild, poly, true, "toSI", "Aij");
110  while (m_Aij.size()<poly.size()) {
111  DenseMatrix* aTemp = new DenseMatrix();
112  aTemp->resize(nsp, nsp, 0.0);
113  m_Aij.push_back(aTemp);
114  }
115  for (int i = 0; i < (int)poly.size(); i++) {
116  (*m_Aij[i])(iSpecies,jSpecies) = poly[i];
117  }
118  }
119 
120  if (xmlChild.hasChild("Bij")) {
121  vector_fp poly;
122  getFloatArray(xmlChild, poly, true, "toSI", "Bij");
123  while (m_Bij.size() < poly.size()) {
124  DenseMatrix* bTemp = new DenseMatrix();
125  bTemp->resize(nsp, nsp, 0.0);
126  m_Bij.push_back(bTemp);
127  }
128  for (size_t i=0; i<poly.size(); i++) {
129  (*m_Bij[i])(iSpecies,jSpecies) = poly[i];
130  }
131  }
132 
133  if (xmlChild.hasChild("Hij")) {
134  vector_fp poly;
135  getFloatArray(xmlChild, poly, true, "actEnergy", "Hij");
136  while (m_Hij.size()<poly.size()) {
137  DenseMatrix* hTemp = new DenseMatrix();
138  hTemp->resize(nsp, nsp, 0.0);
139  m_Hij.push_back(hTemp);
140  }
141  for (size_t i=0; i<poly.size(); i++) {
142  (*m_Hij[i])(iSpecies,jSpecies) = poly[i];
143  (*m_Hij[i])(iSpecies,jSpecies) /= GasConstant;
144  }
145  }
146 
147  if (xmlChild.hasChild("Sij")) {
148  vector_fp poly;
149  getFloatArray(xmlChild, poly, true, "actEnergy", "Sij");
150  while (m_Sij.size()<poly.size()) {
151  DenseMatrix* sTemp = new DenseMatrix();
152  sTemp->resize(nsp, nsp, 0.0);
153  m_Sij.push_back(sTemp);
154  }
155  for (size_t i=0; i<poly.size(); i++) {
156  (*m_Sij[i])(iSpecies,jSpecies) = poly[i];
157  (*m_Sij[i])(iSpecies,jSpecies) /= GasConstant;
158  }
159  }
160 
161  if (xmlChild.hasChild("Dij")) {
162  m_Dij(iSpecies,jSpecies) = getFloat(xmlChild, "Dij", "toSI");
163  m_Dij(jSpecies,iSpecies) = m_Dij(iSpecies,jSpecies) ;
164  }
165  }
166 }
167 
169 {
170  *this = right; //use assignment operator to do other work
171 }
172 
173 LiquidTranInteraction& LiquidTranInteraction::operator=(const LiquidTranInteraction& right)
174 {
175  if (&right != this) {
176  m_model = right.m_model;
177  m_property = right.m_property;
178  m_thermo = right.m_thermo;
179  //m_trParam = right.m_trParam;
180  m_Aij = right.m_Aij;
181  m_Bij = right.m_Bij;
182  m_Eij = right.m_Eij;
183  m_Hij = right.m_Hij;
184  m_Sij = right.m_Sij;
185  m_Dij = right.m_Dij;
186  }
187  return *this;
188 }
189 
190 LTI_Solvent::LTI_Solvent(TransportPropertyType tp_ind) :
191  LiquidTranInteraction(tp_ind)
192 {
193  m_model = LTI_MODEL_SOLVENT;
194 }
195 
196 doublereal LTI_Solvent::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
197 {
198  size_t nsp = m_thermo->nSpecies();
199  doublereal temp = m_thermo->temperature();
200  vector_fp molefracs(nsp);
201  m_thermo->getMoleFractions(&molefracs[0]);
202 
203  doublereal value = 0.0;
204 
205  //if weightings are specified, use those
206  if (speciesWeight) {
207  for (size_t k = 0; k < nsp; k++) {
208  // should be: molefracs[k] = molefracs[k]*speciesWeight[k]; for consistency, but weight(solvent)=1?
209  }
210  } else {
211  throw CanteraError("LTI_Solvent::getMixTransProp","You should be specifying the speciesWeight");
212  }
213 
214  for (size_t i = 0; i < nsp; i++) {
215  //presume that the weighting is set to 1.0 for solvent and 0.0 for everything else.
216  value += speciesValues[i] * speciesWeight[i];
217  if (i == 0) {
218  AssertTrace(speciesWeight[i] == 1.0);
219  } else {
220  AssertTrace(speciesWeight[i] == 0.0);
221  }
222  for (size_t j = 0; j < nsp; j++) {
223  for (size_t k = 0; k < m_Aij.size(); k++) {
224  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
225  }
226  for (size_t k = 0; k < m_Bij.size(); k++) {
227  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
228  }
229  }
230  }
231 
232  return value;
233 }
234 
235 doublereal LTI_Solvent::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
236 {
237  size_t nsp = m_thermo->nSpecies();
238  doublereal temp = m_thermo->temperature();
239  vector_fp molefracs(nsp);
240  m_thermo->getMoleFractions(&molefracs[0]);
241 
242  doublereal value = 0.0;
243 
244  for (size_t k = 0; k < nsp; k++) {
245  // should be: molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight(); for consistency, but weight(solvent)=1?
246  }
247 
248  for (size_t i = 0; i < nsp; i++) {
249  //presume that the weighting is set to 1.0 for solvent and 0.0 for everything else.
250  value += LTPptrs[i]->getSpeciesTransProp() * LTPptrs[i]->getMixWeight();
251  for (size_t j = 0; j < nsp; j++) {
252  for (size_t k = 0; k < m_Aij.size(); k++) {
253  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
254  }
255  for (size_t k = 0; k < m_Bij.size(); k++) {
256  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
257  }
258  }
259  }
260 
261  return value;
262 }
263 
264 void LTI_Solvent::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
265 {
266  mat = (*m_Aij[0]);
267 }
268 
269 doublereal LTI_MoleFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
270 {
271  size_t nsp = m_thermo->nSpecies();
272  doublereal temp = m_thermo->temperature();
273  vector_fp molefracs(nsp);
274  m_thermo->getMoleFractions(&molefracs[0]);
275 
276  doublereal value = 0;
277 
278  //if weightings are specified, use those
279  if (speciesWeight) {
280  for (size_t k = 0; k < nsp; k++) {
281  molefracs[k] = molefracs[k]*speciesWeight[k];
282  }
283  } else {
284  throw CanteraError("LTI_MoleFracs::getMixTransProp","You should be specifying the speciesWeight");
285  }
286 
287  for (size_t i = 0; i < nsp; i++) {
288  value += speciesValues[i] * molefracs[i];
289  for (size_t j = 0; j < nsp; j++) {
290  for (size_t k = 0; k < m_Aij.size(); k++) {
291  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
292  }
293  for (size_t k = 0; k < m_Bij.size(); k++) {
294  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
295  }
296  }
297  }
298 
299  return value;
300 }
301 
302 doublereal LTI_MoleFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
303 {
304  size_t nsp = m_thermo->nSpecies();
305  doublereal temp = m_thermo->temperature();
306  vector_fp molefracs(nsp);
307  m_thermo->getMoleFractions(&molefracs[0]);
308 
309  doublereal value = 0;
310 
311  for (size_t k = 0; k < nsp; k++) {
312  molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
313  }
314 
315  for (size_t i = 0; i < nsp; i++) {
316  value += LTPptrs[i]->getSpeciesTransProp() * molefracs[i];
317  for (size_t j = 0; j < nsp; j++) {
318  for (size_t k = 0; k < m_Aij.size(); k++) {
319  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
320  }
321  for (size_t k = 0; k < m_Bij.size(); k++) {
322  value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
323  }
324  }
325  }
326  return value;
327 }
328 
329 doublereal LTI_MassFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
330 {
331  size_t nsp = m_thermo->nSpecies();
332  doublereal temp = m_thermo->temperature();
333  vector_fp massfracs(nsp);
334  m_thermo->getMassFractions(&massfracs[0]);
335 
336  doublereal value = 0;
337 
338  //if weightings are specified, use those
339  if (speciesWeight) {
340  for (size_t k = 0; k < nsp; k++) {
341  massfracs[k] = massfracs[k]*speciesWeight[k];
342  }
343  } else {
344  throw CanteraError("LTI_MassFracs::getMixTransProp","You should be specifying the speciesWeight");
345  }
346 
347  for (size_t i = 0; i < nsp; i++) {
348  value += speciesValues[i] * massfracs[i];
349  for (size_t j = 0; j < nsp; j++) {
350  for (size_t k = 0; k < m_Aij.size(); k++) {
351  value += massfracs[i]*massfracs[j]*(*m_Aij[k])(i,j)*pow(massfracs[i], (int) k);
352  }
353  for (size_t k = 0; k < m_Bij.size(); k++) {
354  value += massfracs[i]*massfracs[j]*(*m_Bij[k])(i,j)*temp*pow(massfracs[i], (int) k);
355  }
356  }
357  }
358 
359  return value;
360 }
361 
362 doublereal LTI_MassFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
363 {
364  size_t nsp = m_thermo->nSpecies();
365  doublereal temp = m_thermo->temperature();
366  vector_fp massfracs(nsp);
367  m_thermo->getMassFractions(&massfracs[0]);
368 
369  doublereal value = 0;
370 
371  for (size_t k = 0; k < nsp; k++) {
372  massfracs[k] = massfracs[k]*LTPptrs[k]->getMixWeight();
373  }
374 
375  for (size_t i = 0; i < nsp; i++) {
376  value += LTPptrs[i]->getSpeciesTransProp() * massfracs[i];
377  for (size_t j = 0; j < nsp; j++) {
378  for (size_t k = 0; k < m_Aij.size(); k++) {
379  value += massfracs[i]*massfracs[j]*(*m_Aij[k])(i,j)*pow(massfracs[i], (int) k);
380  }
381  for (size_t k = 0; k < m_Bij.size(); k++) {
382  value += massfracs[i]*massfracs[j]*(*m_Bij[k])(i,j)*temp*pow(massfracs[i], (int) k);
383  }
384  }
385  }
386 
387  return value;
388 }
389 
390 doublereal LTI_Log_MoleFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
391 {
392  size_t nsp = m_thermo->nSpecies();
393  doublereal temp = m_thermo->temperature();
394  vector_fp molefracs(nsp);
395  m_thermo->getMoleFractions(&molefracs[0]);
396 
397 
398 
399  doublereal value = 0;
400 
401  //if weightings are specified, use those
402  if (speciesWeight) {
403  for (size_t k = 0; k < nsp; k++) {
404  molefracs[k] = molefracs[k]*speciesWeight[k];
405  }
406  } else {
407  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");
408  }
409 
410  for (size_t i = 0; i < nsp; i++) {
411  value += log(speciesValues[i]) * molefracs[i];
412  for (size_t j = 0; j < nsp; j++) {
413  for (size_t k = 0; k < m_Hij.size(); k++) {
414  value += molefracs[i]*molefracs[j]*(*m_Hij[k])(i,j)/temp*pow(molefracs[i], (int) k);
415  }
416  for (size_t k = 0; k < m_Sij.size(); k++) {
417  value -= molefracs[i]*molefracs[j]*(*m_Sij[k])(i,j)*pow(molefracs[i], (int) k);
418  }
419  }
420  }
421 
422  return exp(value);
423 }
424 
425 doublereal LTI_Log_MoleFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
426 {
427  size_t nsp = m_thermo->nSpecies();
428  doublereal temp = m_thermo->temperature();
429  vector_fp molefracs(nsp);
430  m_thermo->getMoleFractions(&molefracs[0]);
431 
432 
433  doublereal value = 0;
434 
435  //if weightings are specified, use those
436 
437  for (size_t k = 0; k < nsp; k++) {
438  molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
439  }
440 
441  for (size_t i = 0; i < nsp; i++) {
442  value += log(LTPptrs[i]->getSpeciesTransProp()) * molefracs[i];
443  for (size_t j = 0; j < nsp; j++) {
444  for (size_t k = 0; k < m_Hij.size(); k++) {
445  value += molefracs[i]*molefracs[j]*(*m_Hij[k])(i,j)/temp*pow(molefracs[i], (int) k);
446  }
447  for (size_t k = 0; k < m_Sij.size(); k++) {
448  value -= molefracs[i]*molefracs[j]*(*m_Sij[k])(i,j)*pow(molefracs[i], (int) k);
449  }
450  }
451  }
452 
453  value = exp(value);
454  return value;
455 }
456 
458 {
459  size_t nsp = m_thermo->nSpecies();
460  m_diagonals.resize(nsp, 0);
461 
462  for (size_t k = 0; k < nsp; k++) {
463  Cantera::LiquidTransportData& ltd = trParam.LTData[k];
464  if (ltd.speciesDiffusivity) {
465  m_diagonals[k] = ltd.speciesDiffusivity;
466  }
467  }
468 }
469 
470 doublereal LTI_Pairwise_Interaction::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
471 {
472  size_t nsp = m_thermo->nSpecies();
473  vector_fp molefracs(nsp);
474  m_thermo->getMoleFractions(&molefracs[0]);
475 
476  doublereal value = 0;
477 
478  throw LTPmodelError("Calling LTI_Pairwise_Interaction::getMixTransProp does not make sense.");
479 
480  return value;
481 }
482 
483 doublereal LTI_Pairwise_Interaction::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
484 {
485  size_t nsp = m_thermo->nSpecies();
486  vector_fp molefracs(nsp);
487  m_thermo->getMoleFractions(&molefracs[0]);
488 
489  doublereal value = 0;
490 
491  throw LTPmodelError("Calling LTI_Pairwise_Interaction::getMixTransProp does not make sense.");
492 
493  return value;
494 }
495 
496 void LTI_Pairwise_Interaction::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
497 {
498  size_t nsp = m_thermo->nSpecies();
499  doublereal temp = m_thermo->temperature();
500  vector_fp molefracs(nsp);
501  m_thermo->getMoleFractions(&molefracs[0]);
502 
503  mat.resize(nsp, nsp, 0.0);
504  for (size_t i = 0; i < nsp; i++)
505  for (size_t j = 0; j < i; j++) {
506  mat(i,j) = mat(j,i) = exp(m_Eij(i,j) / temp) / m_Dij(i,j);
507  }
508 
509  for (size_t i = 0; i < nsp; i++)
510  if (mat(i,i) == 0.0 && m_diagonals[i]) {
511  mat(i,i) = 1.0 / m_diagonals[i]->getSpeciesTransProp() ;
512  }
513 }
514 
516 {
517  size_t nsp = m_thermo->nSpecies();
518  size_t nsp2 = nsp*nsp;
519 
520  m_ionCondMix = 0;
521  m_ionCondMixModel = trParam.ionConductivity;
522  m_ionCondSpecies.resize(nsp,0);
523  m_mobRatMix.resize(nsp,nsp,0.0);
524  m_mobRatMixModel.resize(nsp2);
525  m_mobRatSpecies.resize(nsp2);
526  m_selfDiffMix.resize(nsp,0.0);
527  m_selfDiffMixModel.resize(nsp);
528  m_selfDiffSpecies.resize(nsp);
529 
530  for (size_t k = 0; k < nsp2; k++) {
531  m_mobRatMixModel[k] = trParam.mobilityRatio[k];
532  m_mobRatSpecies[k].resize(nsp,0);
533  }
534  for (size_t k = 0; k < nsp; k++) {
535  m_selfDiffMixModel[k] = trParam.selfDiffusion[k];
536  m_selfDiffSpecies[k].resize(nsp,0);
537  }
538 
539  for (size_t k = 0; k < nsp; k++) {
540  Cantera::LiquidTransportData& ltd = trParam.LTData[k];
541  m_ionCondSpecies[k] = ltd.ionConductivity;
542  for (size_t j = 0; j < nsp2; j++) {
543  m_mobRatSpecies[j][k] = ltd.mobilityRatio[j];
544  }
545  for (size_t j = 0; j < nsp; j++) {
546  m_selfDiffSpecies[j][k] = ltd.selfDiffusion[j];
547  }
548  }
549 }
550 
551 doublereal LTI_StefanMaxwell_PPN::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
552 {
553  size_t nsp = m_thermo->nSpecies();
554  vector_fp molefracs(nsp);
555  m_thermo->getMoleFractions(&molefracs[0]);
556 
557  doublereal value = 0;
558 
559  throw LTPmodelError("Calling LTI_StefanMaxwell_PPN::getMixTransProp does not make sense.");
560 
561  return value;
562 }
563 
564 doublereal LTI_StefanMaxwell_PPN::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
565 {
566  size_t nsp = m_thermo->nSpecies();
567  vector_fp molefracs(nsp);
568  m_thermo->getMoleFractions(&molefracs[0]);
569 
570  doublereal value = 0;
571 
572  throw LTPmodelError("Calling LTI_StefanMaxwell_PPN::getMixTransProp does not make sense.");
573 
574  return value;
575 }
576 
577 void LTI_StefanMaxwell_PPN::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
578 {
579  IonsFromNeutralVPSSTP* ions_thermo = dynamic_cast<IonsFromNeutralVPSSTP*>(m_thermo);
580  size_t nsp = m_thermo->nSpecies();
581  if (nsp != 3) {
582  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Function may only be called with a 3-ion system");
583  }
584  doublereal temp = m_thermo->temperature();
585  vector_fp molefracs(nsp);
586  m_thermo->getMoleFractions(&molefracs[0]);
587  vector_fp neut_molefracs;
588  ions_thermo->getNeutralMolecMoleFractions(neut_molefracs);
589  vector<size_t> cation;
590  vector<size_t> anion;
591  ions_thermo->getCationList(cation);
592  ions_thermo->getAnionList(anion);
593 
594  // Reaction Coeffs and Charges
595  std::vector<double> viS(6);
596  std::vector<double> charges(3);
597  std::vector<size_t> neutMolIndex(3);
598  ions_thermo->getDissociationCoeffs(viS,charges,neutMolIndex);
599 
600  if (anion.size() != 1) {
601  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Must have one anion only for StefanMaxwell_PPN");
602  }
603  if (cation.size() != 2) {
604  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Must have two cations of equal charge for StefanMaxwell_PPN");
605  }
606  if (charges[cation[0]] != charges[cation[1]]) {
607  throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Cations must be of equal charge for StefanMaxwell_PPN");
608  }
609 
610  m_ionCondMix = m_ionCondMixModel->getMixTransProp(m_ionCondSpecies);
611 
612  MargulesVPSSTP* marg_thermo = dynamic_cast<MargulesVPSSTP*>(ions_thermo->neutralMoleculePhase_);
613  doublereal vol = m_thermo->molarVolume();
614 
615  size_t k = 0;
616  for (size_t j = 0; j < nsp; j++) {
617  for (size_t i = 0; i < nsp; i++) {
618  if (m_mobRatMixModel[k]) {
619  m_mobRatMix(i,j) = m_mobRatMixModel[k]->getMixTransProp(m_mobRatSpecies[k]);
620  if (m_mobRatMix(i,j) > 0.0) {
621  m_mobRatMix(j,i) = 1.0/m_mobRatMix(i,j);
622  }
623  }
624  k++;
625  }
626  }
627 
628 
629  for (k = 0; k < nsp; k++) {
630  m_selfDiffMix[k] = m_selfDiffMixModel[k]->getMixTransProp(m_selfDiffSpecies[k]);
631  }
632 
633  double vP = max(viS[cation[0]],viS[cation[1]]);
634  double vM = viS[anion[0]];
635  double zP = charges[cation[0]];
636  double zM = charges[anion[0]];
637  doublereal xA, xB, eps;
638  doublereal inv_vP_vM_MutualDiff;
639  vector_fp dlnActCoeffdlnN_diag;
640  dlnActCoeffdlnN_diag.resize(neut_molefracs.size(),0.0);
641  marg_thermo->getdlnActCoeffdlnN_diag(&dlnActCoeffdlnN_diag[0]);
642 
643  xA = neut_molefracs[neutMolIndex[cation[0]]];
644  xB = neut_molefracs[neutMolIndex[cation[1]]];
645  eps = (1-m_mobRatMix(cation[1],cation[0]))/(xA+xB*m_mobRatMix(cation[1],cation[0]));
646  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]]);
647 
648  mat.resize(nsp, nsp, 0.0);
649  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;
650  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;
651  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;
652 }
653 
654 doublereal LTI_StokesEinstein::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
655 {
656  size_t nsp = m_thermo->nSpecies();
657  vector_fp molefracs(nsp);
658  m_thermo->getMoleFractions(&molefracs[0]);
659 
660  doublereal value = 0;
661 
662  throw LTPmodelError("Calling LTI_StokesEinstein::getMixTransProp does not make sense.");
663 
664  return value;
665 }
666 
667 doublereal LTI_StokesEinstein::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
668 {
669  size_t nsp = m_thermo->nSpecies();
670  vector_fp molefracs(nsp);
671  m_thermo->getMoleFractions(&molefracs[0]);
672 
673  doublereal value = 0;
674 
675  throw LTPmodelError("Calling LTI_StokesEinstein::getMixTransProp does not make sense.");
676 
677  return value;
678 }
679 
680 void LTI_StokesEinstein::setParameters(LiquidTransportParams& trParam)
681 {
682  size_t nsp = m_thermo->nSpecies();
683  m_viscosity.resize(nsp, 0);
684  m_hydroRadius.resize(nsp, 0);
685  for (size_t k = 0; k < nsp; k++) {
686  Cantera::LiquidTransportData& ltd = trParam.LTData[k];
687  m_viscosity[k] = ltd.viscosity;
688  m_hydroRadius[k] = ltd.hydroRadius;
689  }
690 }
691 
692 void LTI_StokesEinstein::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
693 {
694  size_t nsp = m_thermo->nSpecies();
695  doublereal temp = m_thermo->temperature();
696 
697  vector_fp viscSpec(nsp);
698  vector_fp radiusSpec(nsp);
699 
700  for (size_t k = 0; k < nsp; k++) {
701  viscSpec[k] = m_viscosity[k]->getSpeciesTransProp() ;
702  radiusSpec[k] = m_hydroRadius[k]->getSpeciesTransProp() ;
703  }
704 
705  mat.resize(nsp,nsp, 0.0);
706  for (size_t i = 0; i < nsp; i++)
707  for (size_t j = 0; j < nsp; j++) {
708  mat(i,j) = (6.0 * Pi * radiusSpec[i] * viscSpec[j]) / GasConstant / temp;
709  }
710 }
711 
712 doublereal LTI_MoleFracs_ExpT::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
713 {
714  size_t nsp = m_thermo->nSpecies();
715  doublereal temp = m_thermo->temperature();
716  vector_fp molefracs(nsp);
717  m_thermo->getMoleFractions(&molefracs[0]);
718 
719  doublereal value = 0;
720 
721  //if weightings are specified, use those
722  if (speciesWeight) {
723  for (size_t k = 0; k < nsp; k++) {
724  molefracs[k] = molefracs[k]*speciesWeight[k];
725  }
726  } else {
727  throw CanteraError("LTI_MoleFracs_ExpT::getMixTransProp","You should be specifying the speciesWeight");
728  }
729 
730  for (size_t i = 0; i < nsp; i++) {
731  value += speciesValues[i] * molefracs[i];
732  for (size_t j = 0; j < nsp; j++) {
733  for (size_t k = 0; k < m_Aij.size(); k++) {
734  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k)*exp((*m_Bij[k])(i,j)*temp);
735  }
736  }
737  }
738 
739  return value;
740 }
741 
742 doublereal LTI_MoleFracs_ExpT::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
743 {
744  size_t nsp = m_thermo->nSpecies();
745  doublereal temp = m_thermo->temperature();
746  vector_fp molefracs(nsp);
747  m_thermo->getMoleFractions(&molefracs[0]);
748 
749  doublereal value = 0;
750 
751  for (size_t k = 0; k < nsp; k++) {
752  molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
753  }
754 
755  for (size_t i = 0; i < nsp; i++) {
756  value += LTPptrs[i]->getSpeciesTransProp() * molefracs[i];
757  for (size_t j = 0; j < nsp; j++) {
758  for (size_t k = 0; k < m_Aij.size(); k++) {
759  value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k)*exp((*m_Bij[k])(i,j)*temp);
760  }
761  }
762  }
763  return value;
764 }
765 
766 } //namespace Cantera
thermo_t * m_thermo
pointer to thermo object to get current temperature
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Copy constructor.
TransportPropertyType
Enumeration of the types of transport properties that can be handled by the variables in the various ...
Definition: LTPspecies.h:31
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::vector< LiquidTranInteraction * > mobilityRatio
Vector of pointer to the LiquidTranInteraction object which handles the calculation of the mobility r...
void getNeutralMolecMoleFractions(vector_fp &neutralMoleculeMoleFractions) const
Return the current value of the neutral mole fraction vector.
Header for intermediate ThermoPhase object for phases which employ Gibbs excess free energy based for...
std::vector< DenseMatrix * > m_Hij
Matrix of interaction coefficients for polynomial in molefraction*weight of speciesA (in energy units...
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:527
void getMassFractions(doublereal *const y) const
Get the species mass fractions.
Definition: Phase.cpp:598
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:100
TransportPropertyType m_property
enum indicating what property this is (i.e viscosity)
Class LiquidTransportData holds transport parameters for a specific liquid-phase species.
const doublereal Pi
Pi.
Definition: ct_defs.h:51
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:73
virtual doublereal getMixTransProp(doublereal *speciesValues, doublereal *weightSpecies=0)
Return the mixture transport property value.
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:556
void getMatrixTransProp(DenseMatrix &mat, doublereal *speciesValues=0)
Return the matrix of binary interaction parameters.
LTPspecies * speciesDiffusivity
Model type for the speciesDiffusivity.
void getDissociationCoeffs(vector_fp &fm_neutralMolec_ions, vector_fp &charges, std::vector< size_t > &neutMolIndex) const
Get the Salt Dissociation Coefficients Returns the vector of dissociation coefficients and vector of ...
void getMatrixTransProp(DenseMatrix &mat, doublereal *speciesValues=0)
Return the matrix of binary interaction parameters.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:573
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
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' ...
Header file defining class LiquidTransportParams.
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:257
LiquidTranInteraction * ionConductivity
Object that specifes the ionic Conductivity of the mixture.
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the matrix.
Definition: DenseMatrix.cpp:64
void setParameters(LiquidTransportParams &trParam)
Copy constructor.
doublereal molarVolume() const
Molar volume (m^3/kmol).
Definition: Phase.cpp:673
void getCationList(std::vector< size_t > &cation) const
Get the list of cations in this object.
DenseMatrix m_Dij
Matrix of interactions.
std::string name() const
Returns the name of the XML node.
Definition: xml.h:394
void setParameters(LiquidTransportParams &trParam)
Copy constructor.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
LiquidTranInteraction(TransportPropertyType tp_ind=TP_UNKNOWN)
Constructor.
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...
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:563
std::vector< Cantera::LiquidTransportData > LTData
Species transport parameters.
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:265
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:270
doublereal temperature() const
Temperature (K).
Definition: Phase.h:602
void getAnionList(std::vector< size_t > &anion) const
Get the list of anions in this object.
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
size_t getFloatArray(const XML_Node &node, std::vector< doublereal > &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:323
std::vector< LTPspecies * > mobilityRatio
Model type for the mobility ratio.
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Copy constructor.
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.
LTPspecies * hydroRadius
Model type for the hydroradius.
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:194
std::vector< LTPspecies * > selfDiffusion
Model type for the self diffusion coefficients.
LTPspecies * viscosity
Model type for the viscosity.
MargulesVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Margules approximation for th...
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Copy constructor.
virtual void init(const XML_Node &compModelNode=XML_Node(), thermo_t *thermo=0)
initialize LiquidTranInteraction objects with thermo and XML node
LTPspecies * ionConductivity
Model type for the ionic conductivity.
doublereal getMixTransProp(doublereal *valueSpecies, doublereal *weightSpecies=0)
Copy constructor.
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:583
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
Definition: DenseMatrix.h:71
Exception thrown if an error is encountered while reading the transport database. ...
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of derivatives of the log activity coefficients wrt mole numbers - diagonal only...