Cantera 4.0.0#

Under development

Breaking Changes#

As a new major version, Cantera 4.0 includes a number of backwards-incompatible changes which may require updates to user code. These changes are summarized here, along with some guidance on how to migrate existing code.

C++: Transition to std::span for array arguments#

Methods operating on arrays have been modified to take std::span arguments instead of pointers to unsized arrays or references to std::vector. This approach provides the opportunity to ensure array sizes are correct while providing compatibility with different data containers. For example, Phase::getMoleFractions(double* x) has been replaced with Phase::getMoleFractions(span<double> x).

The following code demonstrates how to use different container types with Cantera’s methods that take span arguments:

using namespace Cantera;

auto soln = newSolution("mech.yaml");
auto phase = soln->thermo();
vector<double> x1(phase->nSpecies());
Eigen::ArrayXd x2 = Eigen::ArrayXd::Zero(phase->nSpecies());

// custom user container for multiple states
MyVector x3(4 * phase->nSpecies());
size_t offset = 2 * phase->nSpecies();

// Old call signatures (Cantera 3.2 and older)
phase->getMoleFractions(x1.data());
phase->getMoleFractions(x2.data());
phase->getMoleFractions(&x3[offset]);

// New call signatures (Cantera 4.0 and newer)
phase->getMoleFractions(x1);
phase->getMoleFractions(asSpan(x2)); // Eigen 3.4.0
phase->getMoleFractions(x2); // Eigen 5.0
phase->getMoleFractions(span<const double>(&x3[offset], phase->nSpecies()));

For methods that had an extra argument specifying array sizes, this argument has been removed. For example, PlasmaPhase::setElectronEnergyLevels(const double* levels, size_t length) is now just PlasmaPhase::setElectronEnergyLevels(span<const double> levels).

Additionally, a number of methods which previously returned references to std::vector have been updated to return std::span instead. For example, const std::vector<double> Phase::molecularWeights() has been replaced with span<const double> Phase::molecularWeights().

New features#

  • Make an analytic Jacobian the default for 1D flame simulations. The species mass-fraction Jacobian columns at interior grid points are evaluated analytically from kinetics concentration-derivative functions instead of by finite differences, which substantially reduces Jacobian construction time, particularly for large reaction mechanisms. The speedup grows with mechanism size as kinetic sparsity increases; measured ~2.4–3× for mechanisms with 53–173 species. For very large mechanisms the O(K³) factorization cost eventually exceeds the evaluation savings (crossover roughly at 400 species with the analytic Jacobian). The jacobian_mode property selects "auto" (the default; analytic where supported, silent fallback to finite differences otherwise), "analytic" (which raises if analytic evaluation was requested but is unavailable because the kinetics lacks composition derivatives or multicomponent transport is active), or "finite-difference". The analytic mode makes the same frozen-transport approximation as the finite-difference Jacobian. See Nonlinear Solver for One-dimensional Flows for details. Also adds Sim1D.eval_jacobian() and Domain1D.global_component_index(). [C++] Adds a pattern-reusing Kinetics::netProductionRates_ddCi overload that refills a caller-owned sparse matrix in place, avoiding repeated sparse assembly.

  • Add Sim1D.solver_stats, which reports per-grid 1D solver statistics (residual evaluation, Jacobian construction, Jacobian factorization, linear solves, and total) as a dictionary of parallel arrays. Timing now uses wall-clock time. The previous per-metric properties (grid_size_stats, jacobian_time_stats, jacobian_count_stats, eval_time_stats, eval_count_stats, time_step_stats) are deprecated in favor of solver_stats.