Cantera
2.0
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
src
thermo
SurfPhase.cpp
Go to the documentation of this file.
1
/**
2
* @file SurfPhase.cpp
3
* Definitions for a simple thermodynamic model of a surface phase
4
* derived from ThermoPhase, assuming an ideal solution model
5
* (see \ref thermoprops and class
6
* \link Cantera::SurfPhase SurfPhase\endlink).
7
*/
8
// Copyright 2002 California Institute of Technology
9
10
#include "
cantera/thermo/SurfPhase.h
"
11
#include "
cantera/thermo/EdgePhase.h
"
12
#include "
cantera/thermo/ThermoFactory.h
"
13
#include "
cantera/base/stringUtils.h
"
14
15
using namespace
ctml;
16
using namespace
std;
17
18
///////////////////////////////////////////////////////////
19
//
20
// class SurfPhase methods
21
//
22
///////////////////////////////////////////////////////////
23
24
namespace
Cantera
25
{
26
27
SurfPhase::SurfPhase(doublereal n0):
28
ThermoPhase
(),
29
m_n0(n0),
30
m_logn0(0.0),
31
m_tmin(0.0),
32
m_tmax(0.0),
33
m_press(
OneAtm
),
34
m_tlast(0.0)
35
{
36
if
(n0 > 0.0) {
37
m_logn0
= log(n0);
38
}
39
setNDim
(2);
40
}
41
42
SurfPhase::SurfPhase
(std::string infile, std::string
id
) :
43
ThermoPhase
(),
44
m_n0(0.0),
45
m_logn0(0.0),
46
m_tmin(0.0),
47
m_tmax(0.0),
48
m_press(
OneAtm
),
49
m_tlast(0.0)
50
{
51
XML_Node
* root =
get_XML_File
(infile);
52
if
(
id
==
"-"
) {
53
id
=
""
;
54
}
55
XML_Node
* xphase =
get_XML_NameID
(
"phase"
, std::string(
"#"
)+
id
, root);
56
if
(!xphase) {
57
throw
CanteraError
(
"SurfPhase::SurfPhase"
,
58
"Couldn't find phase name in file:"
+
id
);
59
}
60
// Check the model name to ensure we have compatibility
61
const
XML_Node
& th = xphase->
child
(
"thermo"
);
62
string
model = th[
"model"
];
63
if
(model !=
"Surface"
&& model !=
"Edge"
) {
64
throw
CanteraError
(
"SurfPhase::SurfPhase"
,
65
"thermo model attribute must be Surface or Edge"
);
66
}
67
importPhase
(*xphase,
this
);
68
}
69
70
71
SurfPhase::SurfPhase
(
XML_Node
& xmlphase) :
72
ThermoPhase
(),
73
m_n0(0.0),
74
m_logn0(0.0),
75
m_tmin(0.0),
76
m_tmax(0.0),
77
m_press(
OneAtm
),
78
m_tlast(0.0)
79
{
80
const
XML_Node
& th = xmlphase.
child
(
"thermo"
);
81
string
model = th[
"model"
];
82
if
(model !=
"Surface"
&& model !=
"Edge"
) {
83
throw
CanteraError
(
"SurfPhase::SurfPhase"
,
84
"thermo model attribute must be Surface or Edge"
);
85
}
86
importPhase
(xmlphase,
this
);
87
}
88
89
// Copy Constructor
90
/*
91
* Copy constructor for the object. Constructed
92
* object will be a clone of this object, but will
93
* also own all of its data.
94
* This is a wrapper around the assignment operator
95
*
96
* @param right Object to be copied.
97
*/
98
SurfPhase::SurfPhase
(
const
SurfPhase
& right) :
99
m_n0(right.m_n0),
100
m_logn0(right.m_logn0),
101
m_tmin(right.m_tmin),
102
m_tmax(right.m_tmax),
103
m_press(right.m_press),
104
m_tlast(right.m_tlast)
105
{
106
*
this
=
operator=
(right);
107
}
108
109
// Assignment operator
110
/*
111
* Assignment operator for the object. Constructed
112
* object will be a clone of this object, but will
113
* also own all of its data.
114
*
115
* @param right Object to be copied.
116
*/
117
SurfPhase
&
SurfPhase::
118
operator=
(
const
SurfPhase
& right)
119
{
120
if
(&right !=
this
) {
121
ThermoPhase::operator=
(right);
122
m_n0
= right.
m_n0
;
123
m_logn0
= right.
m_logn0
;
124
m_tmin
= right.
m_tmin
;
125
m_tmax
= right.
m_tmax
;
126
m_press
= right.
m_press
;
127
m_tlast
= right.
m_tlast
;
128
m_h0
= right.
m_h0
;
129
m_s0
= right.
m_s0
;
130
m_cp0
= right.
m_cp0
;
131
m_mu0
= right.
m_mu0
;
132
m_work
= right.
m_work
;
133
m_pe
= right.
m_pe
;
134
m_logsize
= right.
m_logsize
;
135
}
136
return
*
this
;
137
}
138
139
// Duplicator from the %ThermoPhase parent class
140
/*
141
* Given a pointer to a %ThermoPhase object, this function will
142
* duplicate the %ThermoPhase object and all underlying structures.
143
* This is basically a wrapper around the copy constructor.
144
*
145
* @return returns a pointer to a %ThermoPhase
146
*/
147
ThermoPhase
*
SurfPhase::duplMyselfAsThermoPhase
()
const
148
{
149
SurfPhase
* igp =
new
SurfPhase
(*
this
);
150
return
(
ThermoPhase
*) igp;
151
}
152
153
doublereal
SurfPhase::
154
enthalpy_mole
()
const
155
{
156
if
(
m_n0
<= 0.0) {
157
return
0.0;
158
}
159
_updateThermo
();
160
return
mean_X
(
DATA_PTR
(
m_h0
));
161
}
162
163
SurfPhase::~SurfPhase
()
164
{
165
}
166
167
/*
168
* For a surface phase, the pressure is not a relevant
169
* thermodynamic variable, and so the Enthalpy is equal to the
170
* internal energy.
171
*/
172
doublereal
SurfPhase::
173
intEnergy_mole
()
const
174
{
175
return
enthalpy_mole
();
176
}
177
178
/*
179
* Get the array of partial molar enthalpies of the species
180
* units = J / kmol
181
*/
182
void
SurfPhase::getPartialMolarEnthalpies
(doublereal* hbar)
const
183
{
184
getEnthalpy_RT
(hbar);
185
doublereal rt =
GasConstant
*
temperature
();
186
for
(
size_t
k = 0; k <
m_kk
; k++) {
187
hbar[k] *= rt;
188
}
189
}
190
191
// Returns an array of partial molar entropies of the species in the
192
// solution. Units: J/kmol/K.
193
/*
194
* @param sbar Output vector of species partial molar entropies.
195
* Length = m_kk. units are J/kmol/K.
196
*/
197
void
SurfPhase::getPartialMolarEntropies
(doublereal* sbar)
const
198
{
199
getEntropy_R
(sbar);
200
for
(
size_t
k = 0; k <
m_kk
; k++) {
201
sbar[k] *=
GasConstant
;
202
}
203
}
204
205
// Returns an array of partial molar heat capacities of the species in the
206
// solution. Units: J/kmol/K.
207
/*
208
* @param sbar Output vector of species partial molar entropies.
209
* Length = m_kk. units are J/kmol/K.
210
*/
211
void
SurfPhase::getPartialMolarCp
(doublereal* cpbar)
const
212
{
213
getCp_R
(cpbar);
214
for
(
size_t
k = 0; k <
m_kk
; k++) {
215
cpbar[k] *=
GasConstant
;
216
}
217
}
218
219
// HKM 9/1/11 The partial molar volumes returned here are really partial molar areas.
220
// Partial molar volumes for this phase should actually be equal to zero.
221
void
SurfPhase::getPartialMolarVolumes
(doublereal* vbar)
const
222
{
223
getStandardVolumes
(vbar);
224
}
225
226
void
SurfPhase::getStandardChemPotentials
(doublereal* mu0)
const
227
{
228
_updateThermo
();
229
copy(
m_mu0
.begin(),
m_mu0
.end(), mu0);
230
}
231
232
void
SurfPhase::getChemPotentials
(doublereal* mu)
const
233
{
234
_updateThermo
();
235
copy(
m_mu0
.begin(),
m_mu0
.end(), mu);
236
getActivityConcentrations
(
DATA_PTR
(
m_work
));
237
for
(
size_t
k = 0; k <
m_kk
; k++) {
238
mu[k] +=
GasConstant
*
temperature
() *
239
(log(
m_work
[k]) -
logStandardConc
(k));
240
}
241
}
242
243
void
SurfPhase::getActivityConcentrations
(doublereal* c)
const
244
{
245
getConcentrations
(c);
246
}
247
248
doublereal
SurfPhase::standardConcentration
(
size_t
k)
const
249
{
250
return
m_n0
/
size
(k);
251
}
252
253
doublereal
SurfPhase::logStandardConc
(
size_t
k)
const
254
{
255
return
m_logn0
-
m_logsize
[k];
256
}
257
258
/// The only parameter that can be set is the site density.
259
void
SurfPhase::setParameters
(
int
n, doublereal*
const
c)
260
{
261
if
(n != 1) {
262
throw
CanteraError
(
"SurfPhase::setParameters"
,
263
"Bad value for number of parameter"
);
264
}
265
m_n0
= c[0];
266
if
(
m_n0
<= 0.0) {
267
throw
CanteraError
(
"SurfPhase::setParameters"
,
268
"Bad value for parameter"
);
269
}
270
m_logn0
= log(
m_n0
);
271
}
272
273
void
SurfPhase::getGibbs_RT
(doublereal* grt)
const
274
{
275
_updateThermo
();
276
double
rrt = 1.0/(
GasConstant
*
temperature
());
277
scale
(
m_mu0
.begin(),
m_mu0
.end(), grt, rrt);
278
}
279
280
void
SurfPhase::
281
getEnthalpy_RT
(doublereal* hrt)
const
282
{
283
_updateThermo
();
284
double
rrt = 1.0/(
GasConstant
*
temperature
());
285
scale
(
m_h0
.begin(),
m_h0
.end(), hrt, rrt);
286
}
287
288
void
SurfPhase::getEntropy_R
(doublereal* sr)
const
289
{
290
_updateThermo
();
291
double
rr = 1.0/
GasConstant
;
292
scale
(
m_s0
.begin(),
m_s0
.end(), sr, rr);
293
}
294
295
void
SurfPhase::getCp_R
(doublereal* cpr)
const
296
{
297
_updateThermo
();
298
double
rr = 1.0/
GasConstant
;
299
scale
(
m_cp0
.begin(),
m_cp0
.end(), cpr, rr);
300
}
301
302
void
SurfPhase::getStandardVolumes
(doublereal* vol)
const
303
{
304
_updateThermo
();
305
for
(
size_t
k = 0; k <
m_kk
; k++) {
306
vol[k] = 1.0/
standardConcentration
(k);
307
}
308
}
309
310
void
SurfPhase::getGibbs_RT_ref
(doublereal* grt)
const
311
{
312
getGibbs_RT
(grt);
313
}
314
315
void
SurfPhase::getEnthalpy_RT_ref
(doublereal* hrt)
const
316
{
317
getEnthalpy_RT
(hrt);
318
}
319
320
void
SurfPhase::getEntropy_R_ref
(doublereal* sr)
const
321
{
322
getEntropy_R
(sr);
323
}
324
325
void
SurfPhase::getCp_R_ref
(doublereal* cprt)
const
326
{
327
getCp_R
(cprt);
328
}
329
330
void
SurfPhase::initThermo
()
331
{
332
if
(
m_kk
== 0) {
333
throw
CanteraError
(
"SurfPhase::initThermo"
,
334
"Number of species is equal to zero"
);
335
}
336
m_h0
.resize(
m_kk
);
337
m_s0
.resize(
m_kk
);
338
m_cp0
.resize(
m_kk
);
339
m_mu0
.resize(
m_kk
);
340
m_work
.resize(
m_kk
);
341
m_pe
.resize(
m_kk
, 0.0);
342
vector_fp
cov(
m_kk
, 0.0);
343
cov[0] = 1.0;
344
setCoverages
(
DATA_PTR
(cov));
345
m_logsize
.resize(
m_kk
);
346
for
(
size_t
k = 0; k <
m_kk
; k++) {
347
m_logsize
[k] = log(
size
(k));
348
}
349
}
350
351
void
SurfPhase::setPotentialEnergy
(
int
k, doublereal pe)
352
{
353
m_pe
[k] = pe;
354
_updateThermo
(
true
);
355
}
356
357
void
SurfPhase::setSiteDensity
(doublereal n0)
358
{
359
doublereal x = n0;
360
setParameters
(1, &x);
361
}
362
363
//void SurfPhase::
364
//setElectricPotential(doublereal V) {
365
// for (int k = 0; k < m_kk; k++) {
366
// m_pe[k] = charge(k)*Faraday*V;
367
// }
368
// _updateThermo(true);
369
//}
370
371
372
/**
373
* Set the coverage fractions to a specified
374
* state. This routine converts to concentrations
375
* in kmol/m2, using m_n0, the surface site density,
376
* and size(k), which is defined to be the number of
377
* surface sites occupied by the kth molecule.
378
* It then calls Phase::setConcentrations to set the
379
* internal concentration in the object.
380
*/
381
void
SurfPhase::
382
setCoverages
(
const
doublereal* theta)
383
{
384
double
sum = 0.0;
385
for
(
size_t
k = 0; k <
m_kk
; k++) {
386
sum += theta[k];
387
}
388
if
(sum <= 0.0) {
389
for
(
size_t
k = 0; k <
m_kk
; k++) {
390
cout <<
"theta("
<< k <<
") = "
<< theta[k] << endl;
391
}
392
throw
CanteraError
(
"SurfPhase::setCoverages"
,
393
"Sum of Coverage fractions is zero or negative"
);
394
}
395
for
(
size_t
k = 0; k <
m_kk
; k++) {
396
m_work
[k] =
m_n0
*theta[k]/(sum*
size
(k));
397
}
398
/*
399
* Call the Phase:: class function
400
* setConcentrations.
401
*/
402
setConcentrations
(
DATA_PTR
(
m_work
));
403
}
404
405
void
SurfPhase::
406
setCoveragesNoNorm
(
const
doublereal* theta)
407
{
408
for
(
size_t
k = 0; k <
m_kk
; k++) {
409
m_work
[k] =
m_n0
*theta[k]/(
size
(k));
410
}
411
/*
412
* Call the Phase:: class function
413
* setConcentrations.
414
*/
415
setConcentrations
(
DATA_PTR
(
m_work
));
416
}
417
418
void
SurfPhase::
419
getCoverages
(doublereal* theta)
const
420
{
421
getConcentrations
(theta);
422
for
(
size_t
k = 0; k <
m_kk
; k++) {
423
theta[k] *=
size
(k)/
m_n0
;
424
}
425
}
426
427
void
SurfPhase::
428
setCoveragesByName
(std::string cov)
429
{
430
size_t
kk =
nSpecies
();
431
compositionMap
cc;
432
for
(
size_t
k = 0; k < kk; k++) {
433
cc[
speciesName
(k)] = -1.0;
434
}
435
parseCompString
(cov, cc);
436
doublereal c;
437
vector_fp
cv(kk, 0.0);
438
bool
ifound =
false
;
439
for
(
size_t
k = 0; k < kk; k++) {
440
c = cc[
speciesName
(k)];
441
if
(c > 0.0) {
442
ifound =
true
;
443
cv[k] = c;
444
}
445
}
446
if
(!ifound) {
447
throw
CanteraError
(
"SurfPhase::setCoveragesByName"
,
448
"Input coverages are all zero or negative"
);
449
}
450
setCoverages
(
DATA_PTR
(cv));
451
}
452
453
454
void
SurfPhase::
455
_updateThermo
(
bool
force)
const
456
{
457
doublereal tnow =
temperature
();
458
if
(
m_tlast
!= tnow || force) {
459
m_spthermo
->
update
(tnow,
DATA_PTR
(
m_cp0
),
DATA_PTR
(
m_h0
),
460
DATA_PTR
(
m_s0
));
461
m_tlast
= tnow;
462
doublereal rt =
GasConstant
* tnow;
463
for
(
size_t
k = 0; k <
m_kk
; k++) {
464
m_h0
[k] *= rt;
465
m_s0
[k] *=
GasConstant
;
466
m_cp0
[k] *=
GasConstant
;
467
m_mu0
[k] =
m_h0
[k] - tnow*
m_s0
[k];
468
}
469
m_tlast
= tnow;
470
}
471
}
472
473
void
SurfPhase::
474
setParametersFromXML
(
const
XML_Node
& eosdata)
475
{
476
eosdata.
_require
(
"model"
,
"Surface"
);
477
doublereal n =
getFloat
(eosdata,
"site_density"
,
"toSI"
);
478
if
(n <= 0.0)
479
throw
CanteraError
(
"SurfPhase::setParametersFromXML"
,
480
"missing or negative site density"
);
481
m_n0
= n;
482
m_logn0
= log(
m_n0
);
483
}
484
485
486
void
SurfPhase::setStateFromXML
(
const
XML_Node
& state)
487
{
488
489
double
t;
490
if
(
getOptionalFloat
(state,
"temperature"
, t,
"temperature"
)) {
491
setTemperature
(t);
492
}
493
494
if
(state.
hasChild
(
"coverages"
)) {
495
string
comp =
getChildValue
(state,
"coverages"
);
496
setCoveragesByName
(comp);
497
}
498
}
499
500
// Default constructor
501
EdgePhase::EdgePhase
(doublereal n0) :
SurfPhase
(n0)
502
{
503
setNDim
(1);
504
}
505
506
// Copy Constructor
507
/*
508
* @param right Object to be copied
509
*/
510
EdgePhase::EdgePhase
(
const
EdgePhase
& right) :
511
SurfPhase
(right.m_n0)
512
{
513
setNDim
(1);
514
*
this
=
operator=
(right);
515
}
516
517
// Assignment Operator
518
/*
519
* @param right Object to be copied
520
*/
521
EdgePhase
&
EdgePhase::operator=
(
const
EdgePhase
& right)
522
{
523
if
(&right !=
this
) {
524
SurfPhase::operator=
(right);
525
setNDim
(1);
526
}
527
return
*
this
;
528
}
529
530
// Duplicator from the %ThermoPhase parent class
531
/*
532
* Given a pointer to a %ThermoPhase object, this function will
533
* duplicate the %ThermoPhase object and all underlying structures.
534
* This is basically a wrapper around the copy constructor.
535
*
536
* @return returns a pointer to a %ThermoPhase
537
*/
538
ThermoPhase
*
EdgePhase::duplMyselfAsThermoPhase
()
const
539
{
540
EdgePhase
* igp =
new
EdgePhase
(*
this
);
541
return
(
ThermoPhase
*) igp;
542
}
543
544
void
EdgePhase::
545
setParametersFromXML
(
const
XML_Node
& eosdata)
546
{
547
eosdata.
_require
(
"model"
,
"Edge"
);
548
doublereal n =
getFloat
(eosdata,
"site_density"
,
"toSI"
);
549
if
(n <= 0.0)
550
throw
CanteraError
(
"EdgePhase::setParametersFromXML"
,
551
"missing or negative site density"
);
552
m_n0
= n;
553
m_logn0
= log(
m_n0
);
554
}
555
556
557
}
Generated by
1.8.2