Using surface chemistry in Cantera

410 views
Skip to first unread message

Adhiraj Dasgupta

unread,
Nov 18, 2020, 4:25:06 PM11/18/20
to Cantera Users' Group
Hello all

I am trying to use Cantera 2.4 with heterogeneous chemistry. To this end I created a small C++ program to create a surface and advance it in time.

To create the surface I  use the following code snippet:

       ConstPressureReactor r;
   r.insert(gas);
   r.setInitialVolume(rvol);
   r.setEnergy(1);  // 0 - energy off; 1 - energy on
   r.setChemistry(1);//0 - chemistry off; 1- chemistry on
   Reservoir env;
   env.insert(air);
        
   ReactorSurface rsurf;
   rsurf.setArea(rarea);
   rsurf.setKinetics(&surf);
   rsurf.setReactor(&r);
   double* sCov = new double[surf.nSpecies()];
   rsurf.getCoverages(sCov);
   ReactorNet sim;
   sim.setVerbose(false);
   sim.addReactor(r);


Then in order to advance the surface in time I use the following code:

        sim.advance(tm);

However, in doing so, the coverages for the surface species does not change. It is as if the advance function is not doing anything to the surface species. 

It seems that I am missing a step in the chain, which would properly connect the surface to the gas and trigger reactions.


If anyone can point me in the right direction that would be much appreciated.

Bryan W. Weber

unread,
Dec 3, 2020, 9:16:46 AM12/3/20
to Cantera Users' Group

Adhiraj Dasgupta

unread,
Jan 6, 2021, 10:24:56 AM1/6/21
to Cantera Users' Group
Hi Bryan:

Thank you for your suggestion.

However, even with the "advanceCoverages", the surface chemistry is still not accounted in the reactor simulation.

For example, the code below for the partial-oxidation of CH4 on Pt surface does not produce any CH4 conversion whereas its equivalent code in python shows a conversion. For example, CH4 is converted (i.e., changed from 60% to 45%) to other gaseous species due to the surface-induced oxidation in python whereas C++ code did not show any change in the gas composition (C++ and python files are attached). I am not sure what is missing in the C++ code to make this difference. I would appreciate any help to identify the missing piece in the C++ code, or any C++ example using surface chemistry for a reactor simulation.

//***Surface Reactor - C++ Example:

   //inputs

    string cti_file = "methane_pox_on_pt.cti";
    string comp = "CH4:0.60, O2:0.30, AR:0.10";
    double temp = 600.0;
    double patm = 1.0;
    double tfinal = 1.0;

   // defining phases
    auto gas_sol = newSolution(cti_file, "gas");
    auto gas_ph = gas_sol->thermo();
    auto gas_kin = gas_sol->kinetics();
    gas_ph->setState_TPX(temp, patm*OneAtm, comp);

    auto surf_sol = newSolution(cti_file, "Pt_surf", "None", {gas_sol});
    auto surf_ph = std::dynamic_pointer_cast<SurfPhase>(surf_sol->thermo());
    auto surf_kin = std::dynamic_pointer_cast<InterfaceKinetics>(surf_sol->kinetics());
    surf_ph->setState_TP(temp, patm*OneAtm);

    // advance surface coverage
    surf_kin->advanceCoverages(10.);

    // setting-up surface reactor
    IdealGasReactor reactor;
     reactor.insert(gas_sol);
     reactor.setEnergy(0);
     ReactorSurface react_surf;
     react_surf.setReactor(&reactor);
    react_surf.setKinetics(surf_kin.get());

    // simulating reactor
    ReactorNet sim;
    sim.addReactor(reactor);
    sim.advance(tfinal);


#***Surface Reactor - Python Example:

import cantera as ct

# inputs
cti_file = "methane_pox_on_pt.cti"
temp = 600.0
patm = 1.0
comp = "CH4:0.60, O2:0.30, AR:0.10"
tfinal = 1.0

# defining phases
gas_kin = ct.Solution(cti_file, 'gas')
gas_kin.TPX = temp, ct.one_atm*patm, comp

surf_kin = ct.Interface(cti_file,'Pt_surf', [gas_kin])
surf_kin.TP = temp, ct.one_atm*patm

# advance surface coverage
surf_kin.advance_coverages(10)

# setting-up surface reactor
r = ct.IdealGasReactor(gas_kin, energy='off')
rsurf = ct.ReactorSurface(surf_kin, r)
sim = ct.ReactorNet([r])
sim.advance(tfinal)
SurfReactor_pox.cpp
SurfReactor_pox.py

Ray Speth

unread,
Jan 6, 2021, 11:26:45 AM1/6/21
to Cantera Users' Group

Hi,

It looks like this is not documented very well, but you need to add the surface to the reactor, not the other way around. The ReactorSurface.setReactor method is more of an internal method, which will automatically be called if you call Reactor.addSurface. You can see that this is what is happening in your Python example If you look in reactor.pyx, where ReactorSurface.__init__ calls ReactorSurface.install which then calls Reactor.addSurface.

Regards,
Ray

Adhiraj Dasgupta

unread,
Jan 13, 2021, 1:57:22 PM1/13/21
to Cantera Users' Group
Ray,

thank you, that worked perfectly.

To summarize, I had to replace the line

    react_surf.setReactor(&reactor);

with this:

    reactor.addSurface(&react_surf);

Alireza Lotfollahzade Moghaddam

unread,
Jan 14, 2021, 11:53:28 AM1/14/21
to Cantera Users' Group
Hello all

I tried to simulate a PFR reactor by a series of CSTR reactors. I used the example of the Cantera site and replace some lines to simulate my condition, unfortunately, as others said, it does not count surface reactions. I don't know how to use AddSurface in Python. I would be grateful if you help me.

# import the gas model and set the initial conditions
gas = ct.Solution(cti_file, 'gas')

# import the surface model
surf = ct.Interface(cti_file,'Pt_surf', [gas])

cov = surf.advance_coverages(1)

# create a new reactor
r = ct.IdealGasReactor(gas, energy='on')

# Add the reacting surface to the reactor. The area is set to the desired
# catalyst area in the reactor.
rsurf = ct.ReactorSurface(surf, r, A=cat_area)

sim = ct.ReactorNet([r])

for n in range(NReactors):
    # Set the state of the reservoir to match that of the previous reactor
    gas.TDY = r.thermo.TDY
    upstream.syncState()
    sim.reinitialize()
    sim.advance_to_steady_state()
Reply all
Reply to author
Forward
0 new messages