Skip to content

Electron#700

Closed
BangShiuh wants to merge 139 commits intoCantera:mainfrom
BangShiuh:electron
Closed

Electron#700
BangShiuh wants to merge 139 commits intoCantera:mainfrom
BangShiuh:electron

Conversation

@BangShiuh
Copy link
Copy Markdown
Contributor

@BangShiuh BangShiuh commented Aug 19, 2019

Changes proposed in this pull request:

  • Classes to enable the calculation of electron properties were added.
  • Cross section data for electron in yaml was added.
  • Class IonGasTransport can now use electron mobility and diffusivity calculated from class Electron instead of an estimated constant.
  • Class Kinetics can now take electron temperature to evaluate reaction rate coefficients.
  • Class IonFlow can solve 1D flame with an external electric field.

Note:

I included an example and its data in the example folder and data folder respectively. The data is from LXCAT You can download the data in txt and use BOLOS to convert it into yaml. BOLOS now only support python 2. You can find the python 3 version in my repository, BOLOS , and cs_converter.py in folder samples.

We need to contact lxcat for this PR to be included.

Issues:

  • Sometimes domainTooNarrow can occur for the case with external electric field. I wonder if I can turn it off manually for stage 3 of class IonFlow.

  • The SparseLU solver of Eigen fails for a grid with high maximum eV. This can be solved by set initial electron temperature.

import cantera as ct
import numpy as np

# Simulation parameters
p = ct.one_atm  # pressure [Pa]
Tin = 1000.0  # unburned gas temperature [K]
reactants = 'O2:1.0'  # premixed gas composition
N = p / (ct.boltzmann * Tin)
EN = 100 * 1e-21
E = EN * N

#print(ecs[109].process)
gas = ct.Solution(infile='gri30_ion.cti', efile='lxcat.yaml')
gas.TPX = Tin, p, reactants
gas.set_boltzmann_solver(init_kTe=2.0)

#grid = np.linspace(0.0, 60, num=500) # [eV]
grid = np.linspace(0.0, 80, num=500) # [eV]
gas.set_electron_energy_grid(grid)
gas.electric_field = E
print(gas.electron_temperature)

error.txt

But still I am considering to use SuperLU instead, but it requires some configuration. Eigen

In order to use this module, the superlu headers must be accessible from the include paths, and your binary must be linked to the superlu library and its dependencies. The dependencies depend on how superlu has been compiled. For a cmake based project, you can use our FindSuperLU.cmake module to help you in this task.

@bryanwweber
Copy link
Copy Markdown
Member

@BangShiuh A couple of small administrative things:

  1. There appears to be a file tatus that should not be added here.
  2. In all new/modified files where the license stuff is listed at the top of the file, please use the URL https://cantera.org/license.txt instead of the old one.

Thanks!

@codecov
Copy link
Copy Markdown

codecov bot commented Aug 19, 2019

Codecov Report

Merging #700 into main will increase coverage by 0.04%.
The diff coverage is 73.99%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #700      +/-   ##
==========================================
+ Coverage   71.19%   71.23%   +0.04%     
==========================================
  Files         376      383       +7     
  Lines       46218    46986     +768     
==========================================
+ Hits        32903    33470     +567     
- Misses      13315    13516     +201     
Impacted Files Coverage Δ
include/cantera/kinetics/GasKinetics.h 60.00% <0.00%> (-40.00%) ⬇️
include/cantera/kinetics/Kinetics.h 55.26% <0.00%> (-1.50%) ⬇️
include/cantera/thermo/ThermoPhase.h 27.92% <0.00%> (-0.37%) ⬇️
include/cantera/transport/IonGasTransport.h 100.00% <ø> (ø)
src/oneD/IonFlow.cpp 64.53% <ø> (-0.50%) ⬇️
src/thermo/Phase.cpp 82.03% <0.00%> (-0.60%) ⬇️
src/transport/IonGasTransport.cpp 69.39% <13.72%> (-12.58%) ⬇️
include/cantera/plasma/PlasmaPhase.h 26.78% <26.78%> (ø)
include/cantera/thermo/Phase.h 79.24% <50.00%> (-6.81%) ⬇️
src/plasma/ElectronCrossSection.cpp 68.18% <68.18%> (ø)
... and 22 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 54d1fd7...4e4a913. Read the comment docs.

@BangShiuh BangShiuh force-pushed the electron branch 2 times, most recently from bf3645b to d8a7226 Compare August 21, 2019 00:13
Copy link
Copy Markdown
Member

@speth speth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very substantial and welcome addition to Cantera, so I hope you don't mind the copious number of review comments on the implementation.

First, I have a few questions about names and making sure that they are appropriately descriptive:

  • Would it make sense to name the directory with these new files 'plasma' rather than 'electron'?
  • Would it make more sense for the Electron class to be named PlasmaElectron to avoid any possible confusion with electrons in condensed phases, e.g. the electron-cloud model represented by the MetalPhase class?
  • Likewise, plasma_reaction instead of electron_reaction, since there are other reaction types (electrochemical) that involve electrons?

I do wonder whether it is possible to treat the electron-neutral collision processes more like existing "reaction" types.

Please start the processes of requesting permission from the LXCAT to include the data needed for the tests / sample problem. I don't want to run afoul of their terms of use, but we do need to have some data for the tests and sample problems.

Since the CTI and XML formats are destined for retirement, I would like to suggest adding the input parsing code only for the YAML format, and eliminating the code for converting from XML/CTI.

Please add documentation for the appropriate YAML entries in doc/sphinx/yaml.

bool allow_negative_pre_exponential_factor;
};

class ElectronReaction : public Reaction
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class needs some documentation -- details should go in the Science section of the cantera-website, but this can at least provide a short overview, and especially explain how this relates to the other classes that are being added in this PR.

Comment on lines +189 to +193
throw CanteraError("IonFlow::setSolvingStage",
"solution stage must be set to: "
"1) frozenIonMethod, "
"2) electricFieldEqnMethod");
"2) electricFieldEqnMethod,"
"3) enableBoltzmannEqu");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of confusing and could be reworded - as written, it seems to imply that the names frozenIonMethod, electricFieldEqnMethod, and enableBoltzmannEqu can be used to set the solver "stage", but in fact it is the numeric constants 1, 2, and 3 that matter.

@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Dec 7, 2019

@BangShiuh ... I agree that your proposed functions are a welcome addition to Cantera! While I do not have experience in the field, I have a couple of questions in terms of implementation:

  • how does Electron (or ElectronPlasma) fit into the existing cantera concept that uses ThermoPhase, Kinetics and Transport to specify Solution objects?
  • There currently is only a 1D example. Does your implementation support simple 0D tests or reactor networks as well? (presumably ElectronArrhenius should be suffiently similar to other reactions, which can be evaluated based on the state of an associated substance). Or, to give a different example, surface reactions require a specialized surface phase, but otherwise fit into the general framework.
  • I agree with @speth that it would make sense to introduce a new composite class Plasma. As indicated, I am unsure about having to pass an additional object. Could your solution be tweaked to allow for a Python instantiation via Plasma(ThermoPhase, Kinetics, Transport)?

@BangShiuh
Copy link
Copy Markdown
Contributor Author

BangShiuh commented Dec 15, 2019

@speth ... I agree names (plasma) you suggested.

I do wonder whether it is possible to treat the electron-neutral collision processes more like existing "reaction" types.

It is possible. I can call it plasmaReaction and include a function call getRateCoefficient to get the reaction rate coefficient from class electron. And maybe I can call ElectronReaction =>ElectronTemperatureReaction?

Copy link
Copy Markdown
Member

@ischoegl ischoegl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my previous comments, it would be good to see how this addition fits into existing cantera infrastructure.

//! electron temperature
//! If the reduced electric field is set, electron tempeature is calculated
//! from EEDF.
virtual double electronTemperature();
Copy link
Copy Markdown
Member

@ischoegl ischoegl Dec 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correct that electronTemperature is part of the state of the Plasma (or is it an electric field)? If so, wouldn't it make sense to implement Plasma as a new ThermoPhase-derived object, instead of creating a completely separate interface?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

electronTemperature is the calculated parameter from the state EEDF (electron energy distribution function). I think that class PlasmaElectron is very different from thermoPhase.

Copy link
Copy Markdown
Member

@ischoegl ischoegl Jan 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that it is different from currently implemented ThermoPhase objects. I believe the question is whether it would make sense to tweak the existing interfaces to accommodate your additions, rather than to bypass the existing infrastructure.

Copy link
Copy Markdown
Contributor Author

@BangShiuh BangShiuh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BangShiuh ... I agree that your proposed functions are a welcome addition to Cantera! While I do not have experience in the field, I have a couple of questions in terms of implementation:

* how does `Electron` (or `ElectronPlasma`) fit into the existing cantera concept that uses `ThermoPhase`, `Kinetics` and `Transport` to specify `Solution` objects?

* There currently is only a 1D example. Does your implementation support simple 0D tests or reactor networks as well? (presumably `ElectronArrhenius` should be suffiently similar to other reactions, which can be evaluated based on the state of an associated substance). Or, to give a different example, surface reactions require a specialized _surface phase_, but otherwise fit into the general framework.

* I agree with @speth that it would make sense to introduce a new composite class `Plasma`. As indicated, I am unsure about having to pass an additional object. Could your solution be tweaked to allow for a Python instantiation via `Plasma(ThermoPhase, Kinetics, Transport)`?

PlasmaElectron, ThermoPhase, Kinetics and Transport are combined to form a Plasma object. I will made a new Solution call Plasma.

I do have 0D example, and I will add it to this PR.

@ischoegl Thank you for reviewing my PR!

@BangShiuh
Copy link
Copy Markdown
Contributor Author

I talked to lxcat, and they were not willing to let me install their data. Therefore, I have created my own cross section data for testing. I am having a problem with the class ElectronCrossSection. It acts very weird when adding or deleting member functions, and this prevent me from working on the PlasmaReaction.

Copy link
Copy Markdown
Member

@speth speth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked to lxcat, and they were not willing to let me install their data. Therefore, I have created my own cross section data for testing.

That's unfortunate, but I think your solution sounds fine. In this case, the file data/inputs/lxcat.yaml should be removed, correct?

I think @ischoegl's point about trying to fit this in more with the existing class structure is worth serious consideration. In part, this is because conceptually the state of the electron is part of the thermodynamic state. But furthermore, there would be significant simplifications of the implementation. If you can make PlasmaElectron a child of class ThermoPhase (probably a child of IdealGasPhase), then some of the extra interface methods that are added here, such as Transport.initElectron would be unnecessary, since the Transport class already has a pointer to the ThermoPhase object, and the WeakIonGasTransport class could just cast that pointer to the appropriate type. A similar simplification would apply to the kinetics class, and it would also eliminate the need to introduce a new composite class in the Python interface.

Also, can you rebase this onto the current master? If you have trouble fixing the merge commits, let me know and I can try doing it instead and push the updated branch to this PR.

I am having a problem with the class ElectronCrossSection. It acts very weird when adding or deleting member functions, and this prevent me from working on the PlasmaReaction.

I'm wondering if this is because you have an extra copy of this file in an outdated location in your local copy of the code. I had to change an #include of this header file to get the code to compile (see specifics in comment below).

writelog("Warning: The mole fraction of species {} is more than 0.01",
m_thermo->speciesName(k));
writelog(" but it has no data of cross section.");
writelog("\n");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a good candidate for using the new warn_user function.

@decaluwe
Copy link
Copy Markdown
Member

decaluwe commented Mar 30, 2020

I think @ischoegl's point about trying to fit this in more with the existing class structure is worth serious consideration. In part, this is because conceptually the state of the electron is part of the thermodynamic state.

Just wanted to chime in here: the handling of the electron in general is something on my mind, lately. We currently have a framework to treat it as a species, particularly for the electron-cloud (previously metal) phase, but I'd like there to be a way to treat the electron generally for phases that have both electronic conductivity and variable species composition. i.e. I'd like to have a way to have an electron species that does not factor in to the species composition (mass and mole fraction) calculations, but whose free energy depends solely on the electric potential.

Currently, if I have an electronically-conductive solid which also has variable species, I have to create a separate electron-cloud conductor phase (for example, see the li-ion battery Jupyter notebook).

Anyway, I'm not familiar enough with the work here to know if what I'm proposing is easily incorporated into this work, is already consistent with this work, or is even relevant, and I plan to open an issue over at the enhancements repo, but thought it was at least worth brining the issue up here, in case there is an efficient way to address both issues at one time.

@speth
Copy link
Copy Markdown
Member

speth commented Mar 30, 2020

On the general handling of electrons, I think a new issue in the Enhancements repository makes sense. This PR still involves treating electrons as equivalent to other species, at least in most respects, and I don't think we should burden it with a generalization that affects several existing phase types when we haven't yet worked out how that would work.

@decaluwe
Copy link
Copy Markdown
Member

decaluwe commented Mar 30, 2020 via email

@BangShiuh
Copy link
Copy Markdown
Contributor Author

BangShiuh commented Apr 7, 2020

I got the following issue:

Error compiling Cython file:
------------------------------------------------------------
...
cdef class PlasmaPhase(ThermoPhase):
    """ A class representing a plasma phase"""
    def __cinit__(self, *args, **kwargs):
        if pystr(self.thermo.type()) not in ("WeakIonizedGas"):
            raise TypeError('Underlying ThermoPhase object is of the wrong type.')
        self.plasma = <CxxPlasmaElectron*>(self.thermo)
                     ^
------------------------------------------------------------

interfaces/cython/cantera/plasma.pyx:12:22: Cannot convert 'CxxPlasmaElectron *' to Python object

It is not clear to me why it happened. class InterfacePhase also has self.surf = <CxxSurfPhase*>(self.thermo) but it is fine.

@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Apr 7, 2020

I got the following issue:

Error compiling Cython file:
------------------------------------------------------------
...
cdef class PlasmaPhase(ThermoPhase):
    """ A class representing a plasma phase"""
    def __cinit__(self, *args, **kwargs):
        if pystr(self.thermo.type()) not in ("WeakIonizedGas"):
            raise TypeError('Underlying ThermoPhase object is of the wrong type.')
        self.plasma = <CxxPlasmaElectron*>(self.thermo)
                     ^
------------------------------------------------------------

interfaces/cython/cantera/plasma.pyx:12:22: Cannot convert 'CxxPlasmaElectron *' to Python object

It is not clear to me why it happened. class InterfacePhase also has self.surf = <CxxSurfPhase*>(self.thermo) but it is fine.

You may have to define self.plasma in _cantera.pxd first.

@BangShiuh
Copy link
Copy Markdown
Contributor Author

I got the following issue:

Error compiling Cython file:
------------------------------------------------------------
...
cdef class PlasmaPhase(ThermoPhase):
    """ A class representing a plasma phase"""
    def __cinit__(self, *args, **kwargs):
        if pystr(self.thermo.type()) not in ("WeakIonizedGas"):
            raise TypeError('Underlying ThermoPhase object is of the wrong type.')
        self.plasma = <CxxPlasmaElectron*>(self.thermo)
                     ^
------------------------------------------------------------

interfaces/cython/cantera/plasma.pyx:12:22: Cannot convert 'CxxPlasmaElectron *' to Python object

It is not clear to me why it happened. class InterfacePhase also has self.surf = <CxxSurfPhase*>(self.thermo) but it is fine.

You may have to define self.plasma in _cantera.pxd first.

@ischoegl Thank you for the quick reply. I am too rusty.

@BangShiuh BangShiuh force-pushed the electron branch 2 times, most recently from 046fb17 to 71c961f Compare May 1, 2020 16:02
@BangShiuh
Copy link
Copy Markdown
Contributor Author

BangShiuh commented May 1, 2020

The plasma features are now on PlasmaPhase (thank you for the suggestion!). I am going to merge/rebase this PR. Do you recommend using merge or rebase? I found that rebase is a little headache. Generally I get test fail and compiling fail for rebase and merge, respectively.

I left out potential oneD and zeroD implementation as the PR is large, and I will be working on that in the future. For now, people can try the 0D plasma reactor in the example folder.

@bryanwweber
Copy link
Copy Markdown
Member

Thanks @BangShiuh! Rebasing is definitely preferred

@BangShiuh
Copy link
Copy Markdown
Contributor Author

BangShiuh commented May 2, 2020

I got a compiling issue with fmt. Do you know how to solve it? Thank you.

sudo scons build system_fmt='default'
scons: Reading SConscript files ...
INFO: SCons is using the following Python interpreter: /usr/bin/python2
Configuration variables read from 'cantera.conf' and command line:
python_cmd = '/usr/bin/python3'
system_sundials = 'y'

Checking for C++ header file cmath... (cached) yes
Checking for C++ header file fmt/ostream.h... (cached) no
INFO: Using private installation of fmt library.
INFO: Found fmt version 6.1.2
Checking for C++ header file yaml-cpp/yaml.h... (cached) no
INFO: Using private installation of yaml-cpp library.
Checking for C++ header file gtest/gtest.h... (cached) yes
Checking for C++ header file gmock/gmock.h... (cached) no
INFO: Using Googletest from Git submodule
Checking for C++ header file Eigen/Dense... (cached) yes
INFO: Using system installation of Eigen.
INFO: Found Eigen version 3.2.8
Checking whether GLIBCXX is declared... (cached) yes
Checking whether LIBCPP_VERSION is declared... (cached) no
Checking whether clang is declared... (cached) no
INFO: Found Boost version 1.67
Checking whether boost::core::demangle is declared... (cached) yes
Checking for CVodeCreate(CV_BDF, CV_NEWTON) in C++ library sundials_cvodes... (cached) yes
Checking for double x; log(x) in C library None... (cached) no
INFO: Using system installation of Sundials version 2.5.0.
INFO: Using 'gfortran' to build the Fortran 90 interface
INFO: Using NumPy version 1.16.2.
INFO: Using Cython version 0.29.14.
INFO: Building the full Python package for Python 3.7
scons: done reading SConscript files.
scons: Building targets ...
ConfigBuilder(["build/src/config.h.build"], ["include/cantera/base/config.h.in"])
Generating build/src/config.h.build with the following settings:
CANTERA_SHORT_VERSION "2.5"
CANTERA_VERSION "2.5.0a4"
CT_SUNDIALS_USE_LAPACK 0
CT_SUNDIALS_VERSION 25
CT_USE_DEMANGLE 1
CT_USE_SYSTEM_EIGEN 1
FTN_TRAILING_UNDERSCORE 1
LAPACK_FTN_STRING_LEN_AT_END 1
LAPACK_FTN_TRAILING_UNDERSCORE 1
LAPACK_NAMES_LOWERCASE 1
NEEDS_GENERIC_TEMPL_STATIC_DECL undefined
g++ -o build/src/fortran/fct.o -c -std=c++0x -pthread -O3 -Wno-inline -g -DNDEBUG -Iinclude -Isrc src/fortran/fct.cpp
In file included from include/cantera/ext/fmt/printf.h:14,
from include/cantera/base/fmt.h:23,
from include/cantera/base/ctexceptions.h:14,
from include/cantera/thermo/Phase.h:12,
from include/cantera/thermo/ThermoPhase.h:14,
from include/cantera/kinetics/Kinetics.h:14,
from include/cantera/kinetics/KineticsFactory.h:11,
from src/fortran/fct.cpp:14:
include/cantera/ext/fmt/ostream.h:22:3: error: 'fmt::v5::internal::buffer' {aka 'fmt::v5::internal::basic_buffer'} is not a template
22 | buffer& buffer
;
| ^~~~~~

@bryanwweber
Copy link
Copy Markdown
Member

Looks like there's a version mismatch. Did you run git submodule update and scons clean?

@BangShiuh BangShiuh force-pushed the electron branch 2 times, most recently from 339b77d to 41c1df3 Compare May 5, 2020 12:55
@BangShiuh BangShiuh force-pushed the electron branch 2 times, most recently from 046fb17 to 487f5d5 Compare May 14, 2020 03:13
@BangShiuh
Copy link
Copy Markdown
Contributor Author

@speth I noticed that you pushed to my branch. I didn't know you can do that. Is there a specific reason?

@speth
Copy link
Copy Markdown
Member

speth commented Jan 18, 2021

@BangShiuh - Sorry for not responding sooner. I think the reason I pushed to your branch was to rebase and resolve a merge conflict that had developed, which prevented running the test suite. If you want to force push your local branch back to your Github remote, I think you will see the issue again.

@BangShiuh BangShiuh mentioned this pull request Feb 19, 2022
5 tasks
@BangShiuh BangShiuh marked this pull request as draft March 10, 2022 14:45
@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented May 30, 2022

@BangShiuh … I assume this is superseded by #1190 or others? If I understand correctly, this PR is no longer considered for a merge. Can this be closed?

@ischoegl ischoegl closed this Jun 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants