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