Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix examples #905

Merged
merged 18 commits into from
Aug 21, 2020
Merged

Fix examples #905

merged 18 commits into from
Aug 21, 2020

Conversation

bryanwweber
Copy link
Member

@bryanwweber bryanwweber commented Jul 29, 2020

Changes proposed in this pull request

  • Fixes the Python examples for any changes since they were last run
  • Adds a CI job using find ... -exec python to run the examples and just double check that they all work. I added this because I expect that doing real regression testing in SCons will require quite a bit of effort and so will be some way off. This stop gap will be easy to delete or modify when the time comes. It is not intended to be comprehensive or something a developer can run on their own machine (although copying the command is effective). It is intended as a double check on my work here and a hopeful hedge against future breakage.

Copies of commit messages for reference:

[Cython/Examples] Fix extract_submechanism example

The Reaction.listFromFile() method requires a Kinetics instance when
reading a YAML file. In this case, the appropriate Kinetics instance
could be created by Solution('gri30.yaml'). Since we'd have to create
that object anyways to be able to use Reaction.listFromFile(), we might
as well use the Solution.reactions() method, which returns the same
list as Reaction.listFromFile() for this case where the species
definitions are in the same file as the reaction definitions.

Fix infinite loop in diffusion_flame_extinction.py

This change reworks the abortion criteria for the diffusion flame
extinction example. Previously, the loop was only aborted when the flame
temperature was above the inlet temperature, the difference of the flame
temperature in the prior two iterations was less than the threshold, AND
the change in strain rate parameter was less than the threshold.
However, I found that this combination of conditions was never reached,
because the only way to change the strain rate delta was to have an
extinguished flame, and eventually the flame remains extinguished even
if the delta_alpha is reduced. This leads to an infinite loop, since the
abortion criteria check are only done if the flame is burning. This
change moves the abortion criteria check into the case where the flame
is not burning.

In addition, the flame temperature check is modified to use
np.isclose(). I found that on the last burning iteration, the maximum
flame temperature was only just barely above the oxidizer inlet
temperature. Thus, the result printed to the screen was not very useful.
The change to np.isclose() produces a more useful result for the final
burning iteration before extinction. The last non-burning iteration is
also saved to the output file(s) for reference.

Fix boundary emissivities deprecation warning

The set_boundary_emissivities method is deprecated and will be removed
after Cantera 2.5.0. This change switches one example to use the new
property. The property was also missing from the FlameBase class.

[Example] Specify data file path in flame_fixed_T

This allows the script to be run from the installed location, or from
the root of the source tree.

[Examples] Replace argon.yaml with air.yaml

argon.yaml is deprecated, use air.yaml and specify the composition
instead.

Remaining Fixes

Per #902, we need to determine a final solution for the loading of YAML files with surface mechanisms. I expect the new job to fail until I figure out how to fix that.

If applicable, fill in the issue number this pull request is fixing

Fixes #821, #902, #877, #873, #872

Checklist

  • There is a clear use-case for this code change
  • The commit message has a short title & references relevant issues
  • Build passes (scons build & scons test) and unit tests address code coverage
  • The pull request is ready for review

@bryanwweber bryanwweber force-pushed the fix-examples branch 2 times, most recently from 0ac0d99 to 819a60e Compare July 29, 2020 03:01
@codecov
Copy link

codecov bot commented Jul 29, 2020

Codecov Report

Merging #905 into main will increase coverage by 0.00%.
The diff coverage is 81.81%.

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #905   +/-   ##
=======================================
  Coverage   71.19%   71.19%           
=======================================
  Files         376      376           
  Lines       46211    46218    +7     
=======================================
+ Hits        32898    32903    +5     
- Misses      13313    13315    +2     
Impacted Files Coverage Δ
include/cantera/kinetics/RateCoeffMgr.h 100.00% <ø> (ø)
include/cantera/kinetics/RxnRates.h 92.63% <ø> (ø)
include/cantera/kinetics/StoichManager.h 98.66% <ø> (ø)
include/cantera/oneD/Boundary1D.h 51.66% <0.00%> (-1.79%) ⬇️
include/cantera/thermo/EdgePhase.h 100.00% <ø> (ø)
src/oneD/Boundary1D.cpp 54.79% <100.00%> (+0.44%) ⬆️
src/zeroD/Reactor.cpp 84.92% <100.00%> (+0.05%) ⬆️

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 a9a3a4a...42fbd1d. Read the comment docs.

@ischoegl
Copy link
Member

ischoegl commented Jul 29, 2020

@bryanwweber ... thanks for fixing.

I'm happy to see running of examples added to CI. I'm still not sure why I got so much blow-back when I suggested the same in #892 (which I closed and moved to Cantera/enhancements#60 as it appeared that full regression tests were the preferred option). Doing the same from bash is probably less comprehensive than my scons approach, but ultimately accomplishes the same goal. Edit: I reopened #892 for discussion.

PS: the one issue that came up with #892 are DeprecationWarnings, which would be good to add (all it takes is to add the flag -W error::DeprecationWarning: when running examples).

@ischoegl
Copy link
Member

PPS: one other thing that came up in my own tests is poor convergence of 'ion_burner_flame.py - mainly wanted to mention it here also as it took a long time to run.

@ischoegl ischoegl mentioned this pull request Jul 29, 2020
4 tasks
@bryanwweber
Copy link
Member Author

bryanwweber commented Jul 29, 2020

Thanks for the comments @ischoegl! The concern that I had with your previous approach was exactly that it was adding commands to SCons (making that more complicated) without adding what we want to eventually do. As I said, adding the running here is in part to make sure that I've actually fixed what I set out to fix and avoid "It works on my machine!" problems. I would be fine with deleting that CI run before this PR is merged, once all the examples are fixed up, if we think it adds too much overhead. It will be as easy as deleting the lines from the workflow, without having to modify several of the SConstruct/SConscript files. It was an intentional choice not to try to make something that works on all the platforms, since my idea was to have the simplest possible thing to add and the simplest possible thing to remove when the time comes.

The ion_burner_flame.py example does take a very long time to run, and I've also been having some convergence problems.

@ischoegl
Copy link
Member

ischoegl commented Jul 29, 2020

@bryanwweber ... you're welcome.

I am strongly in favor of running examples during CI in one form or another. Ultimately it makes little difference whether this is done using your approach here or what I had put together in #892. Regarding scons, I tried my best to not make it overly complicated; the advantage would be that it can be run on developer's (or less experienced contributor's!) machines without relying on CI, which may be helpful.

@bryanwweber
Copy link
Member Author

The examples appear to be working now, with the exception of ion_burner_flame.py which I don't know how to address. Otherwise, I think this PR is done.

@ischoegl
Copy link
Member

ischoegl commented Aug 7, 2020

@bryanwweber ... I would advocate for a temporary removal of the ion_burner_flame.py example for 2.5, as I do have concerns that a fix would not be simple (see #909, despite not being a root cause). The example appears to have had poor convergence since 2.4 (which is the release where it was introduced).

@bryanwweber
Copy link
Member Author

@ischoegl I'm not in favor of removing the example wholesale. Given the response from Bang-Shiuh in #908, I wonder if issuing a runtime warning and putting a note in the docstring would be more appropriate.

@ischoegl
Copy link
Member

ischoegl commented Aug 9, 2020

@bryanwweber ... I don't think that the intent should be to remove the example, just to not package it for 2.5, as the fix may be more involved (unless @BangShiuh has an idea for how to fix it before the release, which is presumably three weeks out). I believe it to be more important to have the ability to run examples for CI; including an example that is known to fail feels awkward.

PS: A run-time warning is one way to go about it, but the outcome would be to always have a failing test in CI.

@ischoegl
Copy link
Member

ischoegl commented Aug 10, 2020

@bryanwweber ... nevermind, I found a band-aid fix for ion_burner_flame.py - a reduction of domain size makes things converge - see #912. This is clearly a band-aid; after reviewing the code, there appear to be several issues with IonFlow (I opened #913 to document). However, the fix in #912 should be good enough for 2.5.

@bryanwweber
Copy link
Member Author

Thanks, I saw that change. Does that have any other effect on the solution, are the boundary conditions satisfied, etc.?

@ischoegl
Copy link
Member

ischoegl commented Aug 10, 2020

Does that have any other effect on the solution, are the boundary conditions satisfied, etc.?

The boundary conditions - as implemented - are satisfied by the solver; the physicality is a different issue. Curiously, @BangShiuh removed the offending dYdz condition in #700 - which is still pending. I just verified that this works for both examples; I just added this to #912 so #909 can be closed. I opened a separate issue report #913 summarizing non-trivial items I found while looking over the code.

@ischoegl
Copy link
Member

ischoegl commented Aug 20, 2020

@bryanwweber ... I saw that you cherry-picked the commits from #912 as discussed 👍. Beyond, I think #899 is ready to be merged as long as my updated comment is ok.

Copy link
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 think this is mostly fine, with a few small changes.

data/sofc.yaml Outdated Show resolved Hide resolved
include/cantera/thermo/EdgePhase.h Show resolved Hide resolved
src/oneD/Boundary1D.cpp Outdated Show resolved Hide resolved
@ischoegl
Copy link
Member

@bryanwweber ... the conflict that just popped up is due to 7c42402 (where a smaller fix was just merged in #899). I didn't realize that I found issues twice with the same file.

@bryanwweber
Copy link
Member Author

Thanks @ischoegl I'll sort out the conflict and amend the commit

bryanwweber and others added 18 commits August 20, 2020 14:16
When loading reactions from a YAML file, an instance of a Kinetics
object is required so that the species associated with the reactions are
available. The required object is now constructed from the already
loaded species definitions.

Fixes Cantera#821, problem introduced in 1866e35
This change reworks the abortion criteria for the diffusion flame
extinction example. Previously, the loop was only aborted when the flame
temperature was above the inlet temperature, the difference of the flame
temperature in the prior two iterations was less than the threshold, AND
the change in strain rate parameter was less than the threshold.
However, I found that this combination of conditions was never reached,
because the only way to change the strain rate delta was to have an
extinguished flame, and eventually the flame remains extinguished even
if the delta_alpha is reduced. This leads to an infinite loop, since the
abortion criteria check are only done if the flame is burning. This
change moves the abortion criteria check into the case where the flame
is not burning.

In addition, the flame temperature check is modified to use
np.isclose(). I found that on the last burning iteration, the maximum
flame temperature was only just barely above the oxidizer inlet
temperature. Thus, the result printed to the screen was not very useful.
The change to np.isclose() produces a more useful result for the final
burning iteration before extinction. The last non-burning iteration is
also saved to the output file(s) for reference.

Fixes Cantera#872
The set_boundary_emissivities method is deprecated and will be removed
after Cantera 2.5.0. This change switches one example to use the new
property. The property was also missing from the FlameBase class.
This allows the script to be run from the installed location, or from
the root of the source tree.
argon.yaml is deprecated, use air.yaml and specify the composition
instead.
The calculation for the production of gas phase species from
surface reactions assumed that the gas phase species were stored at the
beginning of the rate-of-production array. This is only the case when
the gas ThermoPhase instance is the first phase in the Kinetics thermo
vector, which is not guaranteed to be the case.

It happens that XML input usually forced the gas phase to be the first
phase in the thermo vector, so everything worked out fine. This was
because the associated phase(s) for a surface phase had to be listed in
an XML file, and the XML initializer reads that list to fill the
Kinetics thermo vector.

In the YAML format, the associated phase does not need to be explicitly
listed. Instead, instances of the appropriate phases are passed to the
constructor when the InterfaceKinetics is created. The gas phase can
then come before or after the surface phase, meaning there is no
guarantee of the order of species.

This change checks for the starting index of the gas phase species in
the InterfaceKinetics species-length arrays to make sure that the
appropriate rates of production are added for the gas phase species.

Fixes Cantera#902, Cantera#877, Cantera#873
Adds a getter function for the coverage_enabled property on the
ReactingSurface1D Python class, and the corresponding C++ method.
The switch to the YAML input file revealed that the calculation of the
anode and cathode currents in sofc.py relied on a particular order of
the phases. This change corrects that by finding the index of the
electron "species" in the anode and cathode phases.
Matplotlib issues a UserWarning if the xticklabels are explicitly set
but the xticks are not explicitly set. We choose to set ticks every 360
degrees of crank angle, which corresponds to every 0.02 seconds in the
simulation.
One of the Fortran samples needs to include the extra_inc_dirs variable
so that system header files in non-standard locations will be found.
Use pathlib to write the text content to a file in write_dot. This
automatically closes the file handle after the text is written.

Also modify the reaction_path.py example to use pathlib and subprocess.
These are available since at least Python 3.5 and represent modern
best-practices in Python scripts.
The multiprocess.Pool object must be closed properly, or the process can
hang according to the Python docs. The recommended method for short code
blocks is to use the context manager. The format of the arguments to
Pool is chosen to allow the last line to be de-dented to remove
ambiguity about the definition of the context manager and the content.
pandas v1.1.0 issues a FutureWarning when plotting single columns from a
DataFrame using the Matplotlib pyplot API. This can be avoided by using
the pandas plotting API instead.
The content of ch4_ion.yaml now matches ch4_ion.cti (the file was re-created
using cti2yaml)
A reduction of domain size makes the example more stable.
@bryanwweber
Copy link
Member Author

@speth Thanks for the comments, I believe I addressed all of them. The only other change I was considering was to switch how Reactor.cpp finds the bulk phase offset from the current approach that assumes that species names are unique among all phases to the pointer comparison, as is done in the 1-D code. Any thoughts?

@speth
Copy link
Member

speth commented Aug 21, 2020

Thanks, that looks good to me. I'm not too concerned about that assumption -- I think you'd have a whole bunch of other problems if you re-used species names between phases in an InterfaceKinetics object.

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.

Broken extract_submechanism.py example
3 participants