-
-
Notifications
You must be signed in to change notification settings - Fork 409
Description
Problem description
The ThermoPhase::addSpecies method can be used to add species to a phase dynamically. However, this capability is not compatible with objects such as Reactor or Domain1D, which set internal array sizes based on the number of species in the phase at the time they are created.
In Python, this is protected against by having Solution objects hold a weak reference any Reactor, Domain1D, or Mixture objects that use that Solution. No equivalent exists at the C++ layer, though, and adding species after creating such objects can lead to crashes.
Managing this in a similar way in C++ would have been difficult until recently, but I think the transition to having objects like Domain1D hold the Solution as a shared_ptr (see #1385, for example) should make this more feasible after some of the old routes have been removed following Cantera 3.0. I think one prerequisite will be using shared_ptr<Solution> to set up Reactor objects, which have not had this change yet.
Steps to reproduce
Replace the integration loop in samples/cxx/combustor/combustor.cpp with the following:
bool added = false;
while (tnow < tfinal) {
tnow += 0.005;
sim.advance(tnow);
tres = combustor.mass()/v.massFlowRate();
f << tnow << ", "
<< combustor.temperature() << ", "
<< tres << ", ";
ThermoPhase& c = combustor.contents();
for (size_t i = 0; i < k_out.size(); i++) {
f << c.moleFraction(k_out[i]) << ", ";
}
f << std::endl;
if (!added) {
auto c6h6 = make_shared<Species>("C6H6", Composition({{"C", 6}, {"H", 6}}));
auto spthermo = c6h6->thermo->parameters();
spthermo.applyUnits();
c6h6->thermo = newSpeciesThermo(spthermo);
gas->addSpecies(c6h6);
added = true;
}
}(also requires adding includes for cantera/thermo/Species.h and cantera/thermo/SpeciesThermoFactory.h)
Behavior
The above segfaults after the first timestep.
Additional context
Initially discussed in PR review for #1456.