mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
Remove deprecated Python code
This commit is contained in:
parent
9d520d5278
commit
ab46f66601
@ -20,7 +20,7 @@ InterfaceKinetics
|
|||||||
Reactions
|
Reactions
|
||||||
---------
|
---------
|
||||||
|
|
||||||
These classes contain the definition of a single reaction, independent of a specific
|
This class contains the definition of a single reaction, independent of a specific
|
||||||
`Kinetics` object. Reaction rate evaluation is handled by `ReactionRate` objects.
|
`Kinetics` object. Reaction rate evaluation is handled by `ReactionRate` objects.
|
||||||
|
|
||||||
Reaction
|
Reaction
|
||||||
@ -28,26 +28,6 @@ Reaction
|
|||||||
.. autoclass:: Reaction
|
.. autoclass:: Reaction
|
||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
|
|
||||||
ThreeBodyReaction
|
|
||||||
^^^^^^^^^^^^^^^^^
|
|
||||||
.. autoclass:: ThreeBodyReaction
|
|
||||||
:no-undoc-members:
|
|
||||||
|
|
||||||
FalloffReaction
|
|
||||||
^^^^^^^^^^^^^^^
|
|
||||||
.. autoclass:: FalloffReaction
|
|
||||||
:no-undoc-members:
|
|
||||||
|
|
||||||
ChemicallyActivatedReaction
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
.. autoclass:: ChemicallyActivatedReaction
|
|
||||||
:no-undoc-members:
|
|
||||||
|
|
||||||
CustomReaction
|
|
||||||
^^^^^^^^^^^^^^
|
|
||||||
.. autoclass:: CustomReaction
|
|
||||||
:no-undoc-members:
|
|
||||||
|
|
||||||
|
|
||||||
Reaction Rates
|
Reaction Rates
|
||||||
--------------
|
--------------
|
||||||
|
@ -35,30 +35,10 @@ ImpingingJet
|
|||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
.. autoclass:: ImpingingJet
|
.. autoclass:: ImpingingJet
|
||||||
|
|
||||||
IonFreeFlame
|
|
||||||
^^^^^^^^^^^^
|
|
||||||
.. autoclass:: IonFreeFlame
|
|
||||||
|
|
||||||
.. autoattribute:: E
|
|
||||||
.. autoattribute:: electric_field_enabled
|
|
||||||
.. automethod:: solve
|
|
||||||
|
|
||||||
IonBurnerFlame
|
|
||||||
^^^^^^^^^^^^^^
|
|
||||||
.. autoclass:: IonBurnerFlame
|
|
||||||
|
|
||||||
.. autoattribute:: E
|
|
||||||
.. autoattribute:: electric_field_enabled
|
|
||||||
.. automethod:: solve
|
|
||||||
|
|
||||||
Flow Domains
|
Flow Domains
|
||||||
------------
|
------------
|
||||||
|
|
||||||
IdealGasFlow
|
|
||||||
^^^^^^^^^^^^
|
|
||||||
.. autoclass:: IdealGasFlow(thermo)
|
|
||||||
:inherited-members:
|
|
||||||
|
|
||||||
FreeFlow
|
FreeFlow
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
.. autoclass:: FreeFlow(thermo)
|
.. autoclass:: FreeFlow(thermo)
|
||||||
@ -67,9 +47,6 @@ AxisymmetricFlow
|
|||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
.. autoclass:: AxisymmetricFlow(thermo)
|
.. autoclass:: AxisymmetricFlow(thermo)
|
||||||
|
|
||||||
IonFlow
|
|
||||||
^^^^^^^
|
|
||||||
.. autoclass:: IonFlow(thermo)
|
|
||||||
|
|
||||||
Boundaries
|
Boundaries
|
||||||
----------
|
----------
|
||||||
|
@ -469,24 +469,6 @@ cdef class ReactingSurface1D(Boundary1D):
|
|||||||
def __get__(self):
|
def __get__(self):
|
||||||
return self.surface
|
return self.surface
|
||||||
|
|
||||||
def set_kinetics(self, Kinetics kin):
|
|
||||||
"""Set the kinetics manager (surface reaction mechanism object).
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; set `Kinetics` when instantiating
|
|
||||||
`ReactingSurface1D` instead.
|
|
||||||
"""
|
|
||||||
warnings.warn("ReactingSurface1D.set_kinetics: Method to be removed after "
|
|
||||||
"Cantera 3.0; set 'Kinetics' when instantiating 'ReactingSurface1D' "
|
|
||||||
"instead.", DeprecationWarning)
|
|
||||||
if pystr(kin.kinetics.kineticsType()) not in ("surface", "edge"):
|
|
||||||
raise TypeError('Kinetics object must be derived from '
|
|
||||||
'InterfaceKinetics.')
|
|
||||||
self.surf.setKinetics(kin.base.kinetics())
|
|
||||||
self.surface = kin
|
|
||||||
self.surface._references[self._weakref_proxy] = True
|
|
||||||
|
|
||||||
property coverage_enabled:
|
property coverage_enabled:
|
||||||
"""Controls whether or not to solve the surface coverage equations."""
|
"""Controls whether or not to solve the surface coverage equations."""
|
||||||
def __set__(self, value):
|
def __set__(self, value):
|
||||||
@ -738,82 +720,6 @@ cdef class AxisymmetricFlow(_FlowBase):
|
|||||||
_domain_type = "axisymmetric-flow"
|
_domain_type = "axisymmetric-flow"
|
||||||
|
|
||||||
|
|
||||||
cdef class IdealGasFlow(_FlowBase):
|
|
||||||
"""
|
|
||||||
An ideal gas flow domain. Functions `set_free_flow` and
|
|
||||||
`set_axisymmetric_flow` can be used to set different type of flow.
|
|
||||||
|
|
||||||
For the type of axisymmetric flow, the equations solved are the similarity
|
|
||||||
equations for the flow in a finite-height gap of infinite radial extent.
|
|
||||||
The solution variables are:
|
|
||||||
|
|
||||||
*velocity*
|
|
||||||
axial velocity
|
|
||||||
*spread_rate*
|
|
||||||
radial velocity divided by radius
|
|
||||||
*T*
|
|
||||||
temperature
|
|
||||||
*lambda*
|
|
||||||
(1/r)(dP/dr)
|
|
||||||
*Y_k*
|
|
||||||
species mass fractions
|
|
||||||
|
|
||||||
It may be shown that if the boundary conditions on these variables are
|
|
||||||
independent of radius, then a similarity solution to the exact governing
|
|
||||||
equations exists in which these variables are all independent of radius.
|
|
||||||
This solution holds only in in low-Mach-number limit, in which case
|
|
||||||
(dP/dz) = 0, and lambda is a constant. (Lambda is treated as a spatially-
|
|
||||||
varying solution variable for numerical reasons, but in the final solution
|
|
||||||
it is always independent of z.) As implemented here, the governing
|
|
||||||
equations assume an ideal gas mixture. Arbitrary chemistry is allowed, as
|
|
||||||
well as arbitrary variation of the transport properties.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0; replaced by `FreeFlow`,
|
|
||||||
`AxisymmetricFlow` and `UnstrainedFlow`.
|
|
||||||
"""
|
|
||||||
_domain_type = "gas-flow"
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("Class 'IdealGasFlow' to be removed after Cantera 3.0; use "
|
|
||||||
"'FreeFlow', 'AxisymmetricFlow' or 'UnstrainedFlow' instead.",
|
|
||||||
DeprecationWarning)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
cdef class IonFlow(_FlowBase):
|
|
||||||
"""
|
|
||||||
An ion flow domain.
|
|
||||||
|
|
||||||
In an ion flow domain, the electric drift is added to the diffusion flux
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0; replaced by `FreeFlow`,
|
|
||||||
`AxisymmetricFlow` and `UnstrainedFlow`.
|
|
||||||
"""
|
|
||||||
_domain_type = "ion-flow"
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("Class 'IonFlow' to be removed after Cantera 3.0; use 'FreeFlow',"
|
|
||||||
" 'AxisymmetricFlow' or 'UnstrainedFlow' instead.",
|
|
||||||
DeprecationWarning)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def set_solving_stage(self, stage):
|
|
||||||
"""
|
|
||||||
Set the mode for handling ionized species:
|
|
||||||
|
|
||||||
- ``stage == 1``: the fluxes of charged species are set to zero
|
|
||||||
- ``stage == 2``: the electric field equation is solved, and the drift flux for
|
|
||||||
ionized species is evaluated
|
|
||||||
"""
|
|
||||||
warnings.warn("IonFlow.set_solving_stage: Method to be removed after Cantera "
|
|
||||||
"3.0; use 'solving_stage' property instead.", DeprecationWarning)
|
|
||||||
self.solving_stage = stage
|
|
||||||
|
|
||||||
|
|
||||||
cdef class Sim1D:
|
cdef class Sim1D:
|
||||||
"""
|
"""
|
||||||
Class Sim1D is a container for one-dimensional domains. It also holds the
|
Class Sim1D is a container for one-dimensional domains. It also holds the
|
||||||
@ -1057,89 +963,12 @@ cdef class Sim1D:
|
|||||||
dom, comp = self._get_indices(domain, component)
|
dom, comp = self._get_indices(domain, component)
|
||||||
self.sim.setFlatProfile(dom, comp, value)
|
self.sim.setFlatProfile(dom, comp, value)
|
||||||
|
|
||||||
def restore_data(self, domain, states, other_cols, meta):
|
|
||||||
"""
|
|
||||||
Restore a ``domain`` from underlying data. This method is used as
|
|
||||||
a service function for import via `FlameBase.from_solution_array`.
|
|
||||||
|
|
||||||
Derived classes set default values for ``domain`` and ``other``, where
|
|
||||||
defaults describe flow domain and essential non-thermodynamic solution
|
|
||||||
components of the configuration, respectively. An alternative ``domain``
|
|
||||||
(such as inlet, outlet, etc.), can be specified either by name or the
|
|
||||||
corresponding Domain1D object itself.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0. Unused after moving `SolutionArray`
|
|
||||||
interface to the C++ core, except for `FlameBase.from_solution_array`,
|
|
||||||
which itself is deprecated due to a pending removal of ``h5py`` support.
|
|
||||||
"""
|
|
||||||
warnings.warn("Sim1D.restore_data: Method to be removed after Cantera 3.0.",
|
|
||||||
DeprecationWarning)
|
|
||||||
idom = self.domain_index(domain)
|
|
||||||
dom = self.domains[idom]
|
|
||||||
T, P, Y = states
|
|
||||||
if isinstance(P, np.ndarray) and P.size:
|
|
||||||
P = P[0]
|
|
||||||
|
|
||||||
if isinstance(dom, _FlowBase):
|
|
||||||
grid = other_cols['grid']
|
|
||||||
dom.grid = grid
|
|
||||||
xi = (grid - grid[0]) / (grid[-1] - grid[0])
|
|
||||||
self._get_initial_solution()
|
|
||||||
|
|
||||||
# restore temperature and 'other' profiles
|
|
||||||
self.set_profile('T', xi, T)
|
|
||||||
for key, val in other_cols.items():
|
|
||||||
if key in ['grid', 'qdot']:
|
|
||||||
pass
|
|
||||||
elif key in dom.component_names:
|
|
||||||
self.set_profile(key, xi, val)
|
|
||||||
|
|
||||||
# restore species profiles
|
|
||||||
for i, spc in enumerate(self.gas.species_names):
|
|
||||||
self.set_profile(spc, xi, Y[:, i])
|
|
||||||
|
|
||||||
# restore pressure
|
|
||||||
self.P = P
|
|
||||||
|
|
||||||
# restore settings
|
|
||||||
dom.settings = meta
|
|
||||||
|
|
||||||
elif isinstance(dom, Inlet1D):
|
|
||||||
self.gas.TPY = T, P, Y
|
|
||||||
dom.T = T
|
|
||||||
self.P = P
|
|
||||||
dom.Y = Y
|
|
||||||
dom.mdot = other_cols['velocity'] * self.gas.density
|
|
||||||
|
|
||||||
elif isinstance(dom, (Outlet1D, OutletReservoir1D,
|
|
||||||
SymmetryPlane1D, Surface1D)):
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif isinstance(dom, ReactingSurface1D):
|
|
||||||
dom.surface.TPY = T, P, Y
|
|
||||||
|
|
||||||
else:
|
|
||||||
msg = ("Import of '{}' is not implemented")
|
|
||||||
raise NotImplementedError(msg.format(type(self).__name__))
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
""" print the current solution. """
|
""" print the current solution. """
|
||||||
if not self._initialized:
|
if not self._initialized:
|
||||||
self.set_initial_guess()
|
self.set_initial_guess()
|
||||||
self.sim.show()
|
self.sim.show()
|
||||||
|
|
||||||
def show_solution(self):
|
|
||||||
"""
|
|
||||||
print the current solution.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; replaced by `show`.
|
|
||||||
"""
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def set_time_step(self, stepsize, n_steps):
|
def set_time_step(self, stepsize, n_steps):
|
||||||
"""Set the sequence of time steps to try when Newton fails.
|
"""Set the sequence of time steps to try when Newton fails.
|
||||||
|
|
||||||
|
@ -2184,7 +2184,7 @@ def main(argv):
|
|||||||
|
|
||||||
longOptions = ['input=', 'thermo=', 'transport=', 'surface=', 'name=',
|
longOptions = ['input=', 'thermo=', 'transport=', 'surface=', 'name=',
|
||||||
'extra=', 'output=', 'permissive', 'help', 'debug',
|
'extra=', 'output=', 'permissive', 'help', 'debug',
|
||||||
'single-intermediate-temperature', 'quiet', 'no-validate', 'id=']
|
'single-intermediate-temperature', 'quiet', 'no-validate']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
optlist, args = getopt.getopt(argv, 'dh', longOptions)
|
optlist, args = getopt.getopt(argv, 'dh', longOptions)
|
||||||
@ -2213,14 +2213,7 @@ def main(argv):
|
|||||||
quiet = '--quiet' in options
|
quiet = '--quiet' in options
|
||||||
transport_file = options.get('--transport')
|
transport_file = options.get('--transport')
|
||||||
surface_file = options.get('--surface')
|
surface_file = options.get('--surface')
|
||||||
|
phase_name = options.get('--name', 'gas')
|
||||||
if '--id' in options:
|
|
||||||
phase_name = options.get('--id', 'gas')
|
|
||||||
logger.warning("\nDeprecationWarning: "
|
|
||||||
"Option '--id=...' is replaced by '--name=...' and will be "
|
|
||||||
"removed after Cantera 3.0.\n")
|
|
||||||
else:
|
|
||||||
phase_name = options.get('--name', 'gas')
|
|
||||||
|
|
||||||
if not input_file and not thermo_file:
|
if not input_file and not thermo_file:
|
||||||
logger.error('At least one of the arguments "--input=..." or "--thermo=..."'
|
logger.error('At least one of the arguments "--input=..." or "--thermo=..."'
|
||||||
|
@ -8,25 +8,6 @@ import csv as _csv
|
|||||||
import importlib.metadata
|
import importlib.metadata
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
_h5py = None
|
|
||||||
def _import_h5py():
|
|
||||||
"""
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Function to be removed after Cantera 3.0, as ``h5py`` support will be removed.
|
|
||||||
"""
|
|
||||||
# defer h5py import
|
|
||||||
global _h5py
|
|
||||||
if _h5py is not None:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
importlib.metadata.version('h5py')
|
|
||||||
except importlib.metadata.PackageNotFoundError:
|
|
||||||
raise ImportError('Method requires a working h5py installation.')
|
|
||||||
else:
|
|
||||||
import h5py as _h5py
|
|
||||||
|
|
||||||
|
|
||||||
_pandas = None
|
_pandas = None
|
||||||
def _import_pandas():
|
def _import_pandas():
|
||||||
@ -588,10 +569,9 @@ class SolutionArray(SolutionArrayBase):
|
|||||||
# From Kinetics
|
# From Kinetics
|
||||||
'n_total_species', 'n_reactions', 'n_phases', 'reaction_phase_index',
|
'n_total_species', 'n_reactions', 'n_phases', 'reaction_phase_index',
|
||||||
'kinetics_species_index', 'reaction', 'reactions', 'modify_reaction',
|
'kinetics_species_index', 'reaction', 'reactions', 'modify_reaction',
|
||||||
'multiplier', 'set_multiplier', 'reaction_equations',
|
'multiplier', 'set_multiplier', 'reaction_equations', 'reactant_stoich_coeff',
|
||||||
'reactant_stoich_coeff', 'product_stoich_coeff',
|
'product_stoich_coeff', 'reactant_stoich_coeffs', 'product_stoich_coeffs',
|
||||||
'reactant_stoich_coeffs', 'product_stoich_coeffs', 'product_stoich_coeffs3',
|
'product_stoich_coeffs_reversible',
|
||||||
'reactant_stoich_coeffs3', 'product_stoich_coeffs_reversible',
|
|
||||||
# from Transport
|
# from Transport
|
||||||
'transport_model',
|
'transport_model',
|
||||||
]
|
]
|
||||||
@ -1189,30 +1169,6 @@ class SolutionArray(SolutionArrayBase):
|
|||||||
|
|
||||||
return dict(data)
|
return dict(data)
|
||||||
|
|
||||||
def write_csv(self, filename, cols=None, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Write a CSV file named ``filename`` containing the data specified by
|
|
||||||
``cols``. The first row of the CSV file will contain column labels.
|
|
||||||
|
|
||||||
Additional arguments are passed on to `collect_data`. This method works
|
|
||||||
only with 1D `SolutionArray` objects.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; superseded by `save`. Note that
|
|
||||||
`write_csv` does not support escaping of commas within string entries.
|
|
||||||
"""
|
|
||||||
warnings.warn("SolutionArray.write_csv: Superseded by 'save' and will be removed "
|
|
||||||
"after Cantera 3.0.", DeprecationWarning, stacklevel=2)
|
|
||||||
data_dict = self.collect_data(*args, cols=cols, tabular=True, **kwargs)
|
|
||||||
data = np.hstack([d[:, np.newaxis] for d in data_dict.values()])
|
|
||||||
labels = list(data_dict.keys())
|
|
||||||
with open(filename, 'w', newline='') as outfile:
|
|
||||||
writer = _csv.writer(outfile)
|
|
||||||
writer.writerow(labels)
|
|
||||||
for row in data:
|
|
||||||
writer.writerow(row)
|
|
||||||
|
|
||||||
def read_csv(self, filename, normalize=True):
|
def read_csv(self, filename, normalize=True):
|
||||||
"""
|
"""
|
||||||
Read a CSV file named ``filename`` and restore data to the `SolutionArray`
|
Read a CSV file named ``filename`` and restore data to the `SolutionArray`
|
||||||
@ -1356,219 +1312,6 @@ class SolutionArray(SolutionArrayBase):
|
|||||||
self.shape = self._api_shape()
|
self.shape = self._api_shape()
|
||||||
return meta
|
return meta
|
||||||
|
|
||||||
def write_hdf(self, filename, *args, cols=None, group=None, subgroup=None,
|
|
||||||
attrs={}, mode='a', append=False,
|
|
||||||
compression=None, compression_opts=None, **kwargs):
|
|
||||||
"""
|
|
||||||
Write data specified by ``cols`` to an HDF container file named ``filename``.
|
|
||||||
Note that it is possible to write multiple data entries to a single HDF
|
|
||||||
container file, where ``group`` is used to differentiate data.
|
|
||||||
|
|
||||||
An example for the default HDF file structure is:::
|
|
||||||
|
|
||||||
/ Group
|
|
||||||
/group0 Group
|
|
||||||
/group0/some_attr Attribute
|
|
||||||
...
|
|
||||||
/group0/T Dataset
|
|
||||||
...
|
|
||||||
/group0/phase Group
|
|
||||||
/group0/phase/name Attribute
|
|
||||||
/group0/phase/source Attribute
|
|
||||||
|
|
||||||
where ``group0`` is the default name for the top level HDF entry. In
|
|
||||||
addition to datasets, information stored in `SolutionArray.meta` is
|
|
||||||
saved in the form of HDF attributes. An additional intermediate layer may
|
|
||||||
be created using the ``subgroup`` argument.
|
|
||||||
|
|
||||||
:param filename:
|
|
||||||
Name of the HDF container file; typical file extensions are
|
|
||||||
``.hdf``, ``.hdf5`` or ``.h5``.
|
|
||||||
:param cols:
|
|
||||||
A list of any properties of the solution being exported.
|
|
||||||
:param group:
|
|
||||||
Identifier for the group in the container file. If no subgroup is
|
|
||||||
specified, a group represents a `SolutionArray`. If 'None', group
|
|
||||||
names default to 'groupN', with N being the number of pre-existing
|
|
||||||
groups within the HDF container file.
|
|
||||||
:param subgroup:
|
|
||||||
Name identifier for an optional subgroup, with subgroups
|
|
||||||
representing individual `SolutionArray` objects. If 'None', no
|
|
||||||
subgroup is created.
|
|
||||||
:param attrs:
|
|
||||||
Dictionary of user-defined attributes added at the group level
|
|
||||||
(typically used in conjunction with a subgroup argument).
|
|
||||||
:param mode:
|
|
||||||
Mode *h5py* uses to open the output file {'a' to read/write if file
|
|
||||||
exists, create otherwise (default); 'w' to create file, truncate if
|
|
||||||
exists; 'r+' to read/write, file must exist}.
|
|
||||||
:param append:
|
|
||||||
If False, the content of a pre-existing group is deleted before
|
|
||||||
writing the `SolutionArray` in the first position. If True, the
|
|
||||||
current `SolutionArray` objects is appended to the group.
|
|
||||||
:param compression:
|
|
||||||
Pre-defined *h5py* compression filters {None, 'gzip', 'lzf', 'szip'}
|
|
||||||
used for data compression.
|
|
||||||
:param compression_opts:
|
|
||||||
Options for the *h5py* compression filter; for 'gzip', this
|
|
||||||
corresponds to the compression level {None, 0-9}.
|
|
||||||
:return:
|
|
||||||
Group identifier used for storing HDF data.
|
|
||||||
|
|
||||||
Arguments ``compression`` and ``compression_opts`` are mapped to parameters
|
|
||||||
for `h5py.create_dataset`; in both cases, the choices of ``None`` results
|
|
||||||
in default values set by *h5py*.
|
|
||||||
|
|
||||||
Additional arguments (that is, ``*args`` and ``**kwargs``) are passed on to
|
|
||||||
`collect_data`; see `collect_data` for further information. This method
|
|
||||||
requires a working installation of *h5py* (``h5py`` can be installed using
|
|
||||||
pip or conda).
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; use `save` instead. Note that
|
|
||||||
the call is redirected to `save` in order to prevent the creation of a file
|
|
||||||
with legacy HDF format.
|
|
||||||
"""
|
|
||||||
warnings.warn("SolutionArray.write_hdf: To be removed after Cantera 3.0; use "
|
|
||||||
"'save' instead.\n Note that the call is redirected to 'save' in order to "
|
|
||||||
"prevent the creation of a file with legacy HDF format;\nas a consequence, "
|
|
||||||
"some options are no longer supported.", DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
if group is None:
|
|
||||||
raise KeyError("Missing required parameter 'group'.")
|
|
||||||
self.save(filename, name=group, sub=subgroup)
|
|
||||||
return group
|
|
||||||
|
|
||||||
def read_hdf(self, filename, group=None, subgroup=None, force=False, normalize=True):
|
|
||||||
"""
|
|
||||||
Read a dataset from a HDF container file and restore data to the
|
|
||||||
`SolutionArray` object. This method allows for recreation of data
|
|
||||||
previously exported by `write_hdf`.
|
|
||||||
|
|
||||||
:param filename: name of the HDF container file; typical file extensions
|
|
||||||
are ``.hdf``, ``.hdf5`` or ``.h5``.
|
|
||||||
:param group: Identifier for the group in the container file. A group
|
|
||||||
may contain a `SolutionArray` object or additional subgroups.
|
|
||||||
:param subgroup:
|
|
||||||
Optional name identifier for a subgroup representing a `SolutionArray`
|
|
||||||
object to be read. If 'None', no subgroup is assumed to exist.
|
|
||||||
:param force: If False, matching `SolutionArray` source identifiers are
|
|
||||||
enforced (for example, the input file used for the creation of the
|
|
||||||
underlying `Solution` object), with an error being raised if the current
|
|
||||||
source does not match the original source. If True, the error is
|
|
||||||
suppressed.
|
|
||||||
:param normalize: Passed on to `restore_data`. If True, mole or mass
|
|
||||||
fractions are normalized so that they sum up to 1.0. If False, mole
|
|
||||||
or mass fractions are not normalized.
|
|
||||||
:return: User-defined attributes provided to describe the group holding
|
|
||||||
the `SolutionArray` information.
|
|
||||||
|
|
||||||
The method imports data using `restore_data` and requires a working
|
|
||||||
installation of *h5py* (``h5py`` can be installed using pip or conda).
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; use `restore` instead. After
|
|
||||||
Cantera 3.0, HDF import using ``h5py`` will be replaced by native
|
|
||||||
support based on C++ ``HighFive`` and ``HDF5`` libraries.
|
|
||||||
"""
|
|
||||||
if _h5py is None:
|
|
||||||
_import_h5py()
|
|
||||||
|
|
||||||
warnings.warn("SolutionArray.read_hdf: Method to be removed after Cantera 3.0; "
|
|
||||||
"use 'restore' instead.", DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
with _h5py.File(filename, 'r') as hdf:
|
|
||||||
|
|
||||||
groups = list(hdf.keys())
|
|
||||||
if not len(groups):
|
|
||||||
group = ''
|
|
||||||
elif group is None:
|
|
||||||
group = groups[0]
|
|
||||||
|
|
||||||
if not (group in hdf.keys()):
|
|
||||||
msg = ("HDF file does not contain group '{}'; "
|
|
||||||
"available groups are: {}")
|
|
||||||
raise IOError(msg.format(group, list(hdf.keys())))
|
|
||||||
|
|
||||||
# load root and attributes
|
|
||||||
root = hdf[group]
|
|
||||||
|
|
||||||
# identify subgroup
|
|
||||||
if subgroup is not None:
|
|
||||||
sub_names = [key for key, value in root.items()
|
|
||||||
if isinstance(value, _h5py.Group)]
|
|
||||||
if not len(sub_names):
|
|
||||||
msg = "HDF group '{}' does not contain valid data"
|
|
||||||
raise IOError(msg.format(group))
|
|
||||||
|
|
||||||
if subgroup not in sub_names:
|
|
||||||
msg = ("HDF file does not contain data set '{}' within "
|
|
||||||
"group '{}'; available data sets are: {}")
|
|
||||||
raise IOError(msg.format(subgroup, group, sub_names))
|
|
||||||
dgroup = root[subgroup]
|
|
||||||
else:
|
|
||||||
dgroup = root
|
|
||||||
|
|
||||||
root_attrs = dict(root.attrs.items())
|
|
||||||
|
|
||||||
def strip_ext(source):
|
|
||||||
"""Strip extension if source identifies a file name"""
|
|
||||||
out = source
|
|
||||||
for ext in ('.yml', '.yaml'):
|
|
||||||
if source.endswith(ext):
|
|
||||||
out = '.'.join(source.split('.')[:-1])
|
|
||||||
break
|
|
||||||
return out
|
|
||||||
|
|
||||||
# load metadata
|
|
||||||
meta = dict(dgroup.attrs.items())
|
|
||||||
for name, value in dgroup.items():
|
|
||||||
# support one level of recursion
|
|
||||||
if isinstance(value, _h5py.Group):
|
|
||||||
meta[name] = dict(value.attrs.items())
|
|
||||||
|
|
||||||
if "generator" in root_attrs or "generator" in meta:
|
|
||||||
raise IOError("Unable to read Cantera 3.0 HDF format with deprecated "
|
|
||||||
"'read_hdf' method; use 'restore' instead.")
|
|
||||||
|
|
||||||
# ensure that mechanisms are matching
|
|
||||||
if "phase" in dgroup:
|
|
||||||
sol_source = strip_ext(dgroup['phase'].attrs['source']).split("/")[-1]
|
|
||||||
source = strip_ext(self.source)
|
|
||||||
if sol_source != source and not force:
|
|
||||||
msg = ("Sources of thermodynamic phases do not match: '{}' vs "
|
|
||||||
"'{}'; use option 'force' to override this error.")
|
|
||||||
raise IOError(msg.format(sol_source, source))
|
|
||||||
|
|
||||||
self.meta = meta
|
|
||||||
|
|
||||||
# load data
|
|
||||||
data = {}
|
|
||||||
for name, value in dgroup.items():
|
|
||||||
if isinstance(value, _h5py.Group):
|
|
||||||
continue
|
|
||||||
elif value.dtype.type == np.bytes_:
|
|
||||||
data[name] = np.array(value).astype('U')
|
|
||||||
else:
|
|
||||||
data[name] = np.array(value)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.restore_data(data, normalize)
|
|
||||||
except ValueError as error:
|
|
||||||
if "surface" in self._phase.thermo_model:
|
|
||||||
# legacy HDF format uses TDX state information, which is incomplete
|
|
||||||
# for surfaces phases (should be TPX or TPY as density is constant)
|
|
||||||
raise IOError(
|
|
||||||
f"Unable to load surface phase '{subgroup}' from legacy HDF "
|
|
||||||
"format (incomplete phase definition); use 'restore' instead."
|
|
||||||
) from None
|
|
||||||
else:
|
|
||||||
raise error
|
|
||||||
|
|
||||||
return root_attrs
|
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
raise NotImplementedError('SolutionArray object is not picklable')
|
raise NotImplementedError('SolutionArray object is not picklable')
|
||||||
|
|
||||||
|
@ -220,41 +220,3 @@ cdef class Tabulated1(Func1):
|
|||||||
cdef string cxx_string = stringify(f"tabulated-{method}")
|
cdef string cxx_string = stringify(f"tabulated-{method}")
|
||||||
self._func = CxxNewFunc1(cxx_string, arr)
|
self._func = CxxNewFunc1(cxx_string, arr)
|
||||||
self.func = self._func.get()
|
self.func = self._func.get()
|
||||||
|
|
||||||
|
|
||||||
cdef class TabulatedFunction(Tabulated1):
|
|
||||||
"""
|
|
||||||
A `TabulatedFunction` object representing a tabulated function is defined by
|
|
||||||
sample points and corresponding function values. Inputs are specified by
|
|
||||||
two iterable objects containing sample point location and function values.
|
|
||||||
Between sample points, values are evaluated based on the optional argument
|
|
||||||
``method``; options are ``'linear'`` (linear interpolation, default) or
|
|
||||||
``'previous'`` (nearest previous value). Outside the sample interval, the
|
|
||||||
value at the closest end point is returned.
|
|
||||||
|
|
||||||
Examples for `TabulatedFunction` objects are::
|
|
||||||
|
|
||||||
>>> t1 = TabulatedFunction([0, 1, 2], [2, 1, 0])
|
|
||||||
>>> [t1(v) for v in [-0.5, 0, 0.5, 1.5, 2, 2.5]]
|
|
||||||
[2.0, 2.0, 1.5, 0.5, 0.0, 0.0]
|
|
||||||
|
|
||||||
>>> t2 = TabulatedFunction(np.array([0, 1, 2]), np.array([2, 1, 0]))
|
|
||||||
>>> [t2(v) for v in [-0.5, 0, 0.5, 1.5, 2, 2.5]]
|
|
||||||
[2.0, 2.0, 1.5, 0.5, 0.0, 0.0]
|
|
||||||
|
|
||||||
The optional ``method`` keyword argument changes the type of interpolation
|
|
||||||
from the ``'linear'`` default to ``'previous'``::
|
|
||||||
|
|
||||||
>>> t3 = TabulatedFunction([0, 1, 2], [2, 1, 0], method='previous')
|
|
||||||
>>> [t3(v) for v in [-0.5, 0, 0.5, 1.5, 2, 2.5]]
|
|
||||||
[2.0, 2.0, 2.0, 1.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0. Renamed to `Tabulated1`.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn(
|
|
||||||
"TabulatedFunction: To be removed after Cantera 3.0. "
|
|
||||||
"Renamed to 'Tabulated1'.", DeprecationWarning)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
@ -288,25 +288,6 @@ cdef class Kinetics(_SolutionBase):
|
|||||||
return get_from_sparse(self.kinetics.reactantStoichCoeffs(),
|
return get_from_sparse(self.kinetics.reactantStoichCoeffs(),
|
||||||
self.n_total_species, self.n_reactions)
|
self.n_total_species, self.n_reactions)
|
||||||
|
|
||||||
property reactant_stoich_coeffs3:
|
|
||||||
"""
|
|
||||||
The array of reactant stoichiometric coefficients. Element ``[k,i]`` of
|
|
||||||
this array is the reactant stoichiometric coefficient of species ``k`` in
|
|
||||||
reaction ``i``.
|
|
||||||
|
|
||||||
For sparse output, set ``ct.use_sparse(True)``.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0. Replaceable by
|
|
||||||
`Kinetics.reactant_stoich_coeffs`
|
|
||||||
"""
|
|
||||||
def __get__(self):
|
|
||||||
warnings.warn("Kinetics.reactant_stoich_coeffs3: To be removed after "
|
|
||||||
"Cantera 3.0; use property 'reactant_stoich_coeffs' instead.",
|
|
||||||
DeprecationWarning)
|
|
||||||
return self.reactant_stoich_coeffs
|
|
||||||
|
|
||||||
property product_stoich_coeffs:
|
property product_stoich_coeffs:
|
||||||
"""
|
"""
|
||||||
The array of product stoichiometric coefficients. Element ``[k,i]`` of
|
The array of product stoichiometric coefficients. Element ``[k,i]`` of
|
||||||
@ -323,25 +304,6 @@ cdef class Kinetics(_SolutionBase):
|
|||||||
return get_from_sparse(self.kinetics.productStoichCoeffs(),
|
return get_from_sparse(self.kinetics.productStoichCoeffs(),
|
||||||
self.n_total_species, self.n_reactions)
|
self.n_total_species, self.n_reactions)
|
||||||
|
|
||||||
property product_stoich_coeffs3:
|
|
||||||
"""
|
|
||||||
The array of product stoichiometric coefficients. Element ``[k,i]`` of
|
|
||||||
this array is the product stoichiometric coefficient of species ``k`` in
|
|
||||||
reaction ``i``.
|
|
||||||
|
|
||||||
For sparse output, set ``ct.use_sparse(True)``.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0. Replaceable by
|
|
||||||
`Kinetics.product_stoich_coeffs`
|
|
||||||
"""
|
|
||||||
def __get__(self):
|
|
||||||
warnings.warn("Kinetics.product_stoich_coeffs3: Method to be removed after "
|
|
||||||
"Cantera 3.0; use property 'product_stoich_coeffs' instead.",
|
|
||||||
DeprecationWarning)
|
|
||||||
return self.product_stoich_coeffs
|
|
||||||
|
|
||||||
property product_stoich_coeffs_reversible:
|
property product_stoich_coeffs_reversible:
|
||||||
"""
|
"""
|
||||||
The array of product stoichiometric coefficients of reversible reactions.
|
The array of product stoichiometric coefficients of reversible reactions.
|
||||||
|
@ -14,8 +14,6 @@ from . import __version__, __git_commit__, hdf_support
|
|||||||
class FlameBase(Sim1D):
|
class FlameBase(Sim1D):
|
||||||
""" Base class for flames with a single flow domain """
|
""" Base class for flames with a single flow domain """
|
||||||
__slots__ = ('gas',)
|
__slots__ = ('gas',)
|
||||||
#: deprecated and to be removed after Cantera 3.0 here and elsewhere (unused)
|
|
||||||
_other = ()
|
|
||||||
|
|
||||||
def __init__(self, domains, gas, grid=None):
|
def __init__(self, domains, gas, grid=None):
|
||||||
"""
|
"""
|
||||||
@ -33,41 +31,6 @@ class FlameBase(Sim1D):
|
|||||||
self.gas = gas
|
self.gas = gas
|
||||||
self.flame.P = gas.P
|
self.flame.P = gas.P
|
||||||
|
|
||||||
def other_components(self, domain=None):
|
|
||||||
"""
|
|
||||||
The method returns simulation components that are specific to a class
|
|
||||||
derived from `FlameBase` or a specific ``domain`` within the `FlameBase`
|
|
||||||
simulation object. Entries may include:
|
|
||||||
|
|
||||||
* ``grid``: grid point positions along the flame [m]
|
|
||||||
* ``velocity``: normal velocity [m/s]
|
|
||||||
* ``spread_rate``: tangential velocity gradient [1/s]
|
|
||||||
* ``lambda``: radial pressure gradient [N/m^4]
|
|
||||||
* ``eField``: electric field strength
|
|
||||||
|
|
||||||
:param domain:
|
|
||||||
Index of a specific domain within the `Sim1D.domains`
|
|
||||||
list. The default is to return other columns of the `Sim1D` object.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0. After moving SolutionArray HDF
|
|
||||||
export to the C++ core, this method is unused.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.other_components: Method to be removed after "
|
|
||||||
"Cantera 3.0 (unused).", DeprecationWarning, stacklevel=2)
|
|
||||||
if domain is None:
|
|
||||||
return self._other
|
|
||||||
|
|
||||||
dom = self.domains[self.domain_index(domain)]
|
|
||||||
if isinstance(dom, Inlet1D):
|
|
||||||
return tuple([e for e in self._other
|
|
||||||
if e not in {'grid', 'lambda', 'eField'}])
|
|
||||||
elif isinstance(dom, (FreeFlow, AxisymmetricFlow, IdealGasFlow)):
|
|
||||||
return self._other
|
|
||||||
else:
|
|
||||||
return ()
|
|
||||||
|
|
||||||
def set_refine_criteria(self, ratio=10.0, slope=0.8, curve=0.8, prune=0.0):
|
def set_refine_criteria(self, ratio=10.0, slope=0.8, curve=0.8, prune=0.0):
|
||||||
"""
|
"""
|
||||||
Set the criteria used for grid refinement.
|
Set the criteria used for grid refinement.
|
||||||
@ -373,25 +336,6 @@ class FlameBase(Sim1D):
|
|||||||
vals[i] = self.gas.elemental_mole_fraction(m)
|
vals[i] = self.gas.elemental_mole_fraction(m)
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
def solution(self, component, point=None):
|
|
||||||
"""
|
|
||||||
Get the solution at one point or for the full flame domain (if
|
|
||||||
``point=None``) for the specified ``component``. The ``component`` can be
|
|
||||||
specified by name or index.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0 to avoid conflation with `Solution`.
|
|
||||||
Replaceable by `profile` or `value`.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.solution: To be removed after Cantera 3.0. "
|
|
||||||
"Replaceable by 'profile' or 'value'.", DeprecationWarning,
|
|
||||||
stacklevel=2)
|
|
||||||
if point is None:
|
|
||||||
return self.profile(self.flame, component)
|
|
||||||
else:
|
|
||||||
return self.value(self.flame, component, point)
|
|
||||||
|
|
||||||
def set_gas_state(self, point):
|
def set_gas_state(self, point):
|
||||||
"""
|
"""
|
||||||
Set the state of the the `Solution` object used for calculations
|
Set the state of the the `Solution` object used for calculations
|
||||||
@ -404,34 +348,6 @@ class FlameBase(Sim1D):
|
|||||||
self.gas.set_unnormalized_mass_fractions(Y)
|
self.gas.set_unnormalized_mass_fractions(Y)
|
||||||
self.gas.TP = self.value(self.flame, 'T', point), self.P
|
self.gas.TP = self.value(self.flame, 'T', point), self.P
|
||||||
|
|
||||||
def write_csv(self, filename, species='X', quiet=True, normalize=True):
|
|
||||||
"""
|
|
||||||
Write the velocity, temperature, density, and species profiles
|
|
||||||
to a CSV file.
|
|
||||||
|
|
||||||
:param filename:
|
|
||||||
Output file name
|
|
||||||
:param species:
|
|
||||||
Attribute to use obtaining species profiles, for example ``X`` for
|
|
||||||
mole fractions or ``Y`` for mass fractions.
|
|
||||||
:param normalize:
|
|
||||||
Boolean flag to indicate whether the mole/mass fractions should
|
|
||||||
be normalized.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; superseded by `save`.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.write_csv: Superseded by 'save'. To be removed "
|
|
||||||
"after Cantera 3.0.", DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
# save data
|
|
||||||
cols = ('extra', 'T', 'D', species)
|
|
||||||
self.to_array(normalize=normalize).write_csv(filename, cols=cols)
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
print("Solution saved to '{0}'.".format(filename))
|
|
||||||
|
|
||||||
def to_array(self, domain=None, normalize=False):
|
def to_array(self, domain=None, normalize=False):
|
||||||
"""
|
"""
|
||||||
Retrieve domain data as a `SolutionArray` object.
|
Retrieve domain data as a `SolutionArray` object.
|
||||||
@ -452,24 +368,6 @@ class FlameBase(Sim1D):
|
|||||||
dest.shape = dest._api_shape()
|
dest.shape = dest._api_shape()
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
def to_solution_array(self, domain=None, normalize=True):
|
|
||||||
"""
|
|
||||||
Return the solution vector as a `SolutionArray` object.
|
|
||||||
|
|
||||||
Derived classes define default values for *other*.
|
|
||||||
|
|
||||||
By default, the mass or mole fractions will be normalized i.e they
|
|
||||||
sum up to 1.0. If this is not desired, the ``normalize`` argument
|
|
||||||
can be set to ``False``.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; superseded by `to_array`.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.to_solution_array: To be removed after Cantera 3.0. "
|
|
||||||
"Replaceable by 'to_array'.", DeprecationWarning, stacklevel=2)
|
|
||||||
return self.to_array(domain, normalize)
|
|
||||||
|
|
||||||
def from_array(self, arr, domain=None):
|
def from_array(self, arr, domain=None):
|
||||||
"""
|
"""
|
||||||
Restore the solution vector from a `SolutionArray` object.
|
Restore the solution vector from a `SolutionArray` object.
|
||||||
@ -487,30 +385,6 @@ class FlameBase(Sim1D):
|
|||||||
domain = self.domains[self.domain_index(domain)]
|
domain = self.domains[self.domain_index(domain)]
|
||||||
domain._from_array(arr)
|
domain._from_array(arr)
|
||||||
|
|
||||||
def from_solution_array(self, arr, domain=None):
|
|
||||||
"""
|
|
||||||
Restore the solution vector from a `SolutionArray` object.
|
|
||||||
|
|
||||||
Derived classes define default values for *other*.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; replaced by `from_array`.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.from_solution_array: To be removed after Cantera 3.0. "
|
|
||||||
"Replaced by 'from_array'.", DeprecationWarning, stacklevel=2)
|
|
||||||
if domain is None:
|
|
||||||
domain = self.flame
|
|
||||||
else:
|
|
||||||
domain = self.domains[self.domain_index(domain)]
|
|
||||||
other = self.other_components(domain)
|
|
||||||
|
|
||||||
states = arr.TPY
|
|
||||||
other_cols = {e: getattr(arr, e) for e in other
|
|
||||||
if e in arr.extra}
|
|
||||||
meta = arr.meta
|
|
||||||
super().restore_data(domain, states, other_cols, meta)
|
|
||||||
|
|
||||||
def to_pandas(self, species='X', normalize=True):
|
def to_pandas(self, species='X', normalize=True):
|
||||||
"""
|
"""
|
||||||
Return the solution vector as a `pandas.DataFrame`.
|
Return the solution vector as a `pandas.DataFrame`.
|
||||||
@ -529,203 +403,6 @@ class FlameBase(Sim1D):
|
|||||||
cols = ('extra', 'T', 'D', species)
|
cols = ('extra', 'T', 'D', species)
|
||||||
return self.to_array(normalize=normalize).to_pandas(cols=cols)
|
return self.to_array(normalize=normalize).to_pandas(cols=cols)
|
||||||
|
|
||||||
def from_pandas(self, df, restore_boundaries=True, settings=None):
|
|
||||||
"""
|
|
||||||
Restore the solution vector from a `pandas.DataFrame`; currently disabled
|
|
||||||
(`save`/`restore` should be used as an alternative).
|
|
||||||
|
|
||||||
:param df:
|
|
||||||
`pandas.DataFrame` containing data to be restored
|
|
||||||
:param restore_boundaries:
|
|
||||||
Boolean flag to indicate whether boundaries should be restored
|
|
||||||
(default is ``True``)
|
|
||||||
:param settings:
|
|
||||||
dictionary containing simulation settings
|
|
||||||
(see `FlameBase.settings`)
|
|
||||||
|
|
||||||
This method is intended for loading of data that were previously
|
|
||||||
exported by `to_pandas`. The method uses `from_array` and
|
|
||||||
requires a working *pandas* installation. The package ``pandas`` can be
|
|
||||||
installed using pip or conda.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; not implemented.
|
|
||||||
"""
|
|
||||||
# @todo: Discuss implementation that allows for restoration of boundaries
|
|
||||||
raise NotImplementedError("Use 'save'/'restore' as alternatives; "
|
|
||||||
"method to be removed after Cantera 3.0.")
|
|
||||||
|
|
||||||
def write_hdf(self, filename, *args, group=None, species='X', mode='a',
|
|
||||||
description=None, compression=None, compression_opts=0,
|
|
||||||
quiet=True, normalize=True, **kwargs):
|
|
||||||
"""
|
|
||||||
Write the solution vector to a HDF container file.
|
|
||||||
|
|
||||||
The `write_hdf` method preserves the structure of a `FlameBase`-derived
|
|
||||||
object (such as `FreeFlame`). Each simulation is saved as a *group*,
|
|
||||||
whereas individual domains are saved as subgroups. In addition to
|
|
||||||
datasets, information on `Sim1D.settings` and `Domain1D.settings` is
|
|
||||||
saved in form of HDF attributes. The internal HDF file structure is
|
|
||||||
illustrated for a `FreeFlame` output as:::
|
|
||||||
|
|
||||||
/ Group
|
|
||||||
/group0 Group
|
|
||||||
/group0/Sim1D_type Attribute
|
|
||||||
...
|
|
||||||
/group0/flame Group
|
|
||||||
/group0/flame/Domain1D_type Attribute
|
|
||||||
...
|
|
||||||
/group0/flame/T Dataset
|
|
||||||
...
|
|
||||||
/group0/flame/phase Group
|
|
||||||
/group0/products Group
|
|
||||||
/group0/products/Domain1D_type Attribute
|
|
||||||
...
|
|
||||||
/group0/products/T Dataset
|
|
||||||
...
|
|
||||||
/group0/products/phase Group
|
|
||||||
/group0/reactants Group
|
|
||||||
/group0/reactants/Domain1D_type Attribute
|
|
||||||
...
|
|
||||||
/group0/reactants/T Dataset
|
|
||||||
...
|
|
||||||
/group0/reactants/phase Group
|
|
||||||
|
|
||||||
where ``group0`` is the default name for the top level HDF entry, and
|
|
||||||
``reactants``, ``flame`` and ``products`` correspond to domain names.
|
|
||||||
Note that it is possible to save multiple solutions to a single HDF
|
|
||||||
container file.
|
|
||||||
|
|
||||||
:param filename:
|
|
||||||
HDF container file containing data to be restored
|
|
||||||
:param group:
|
|
||||||
Identifier for the group in the container file. A group may contain
|
|
||||||
multiple `SolutionArray` objects.
|
|
||||||
:param species:
|
|
||||||
Attribute to use obtaining species profiles, for example ``X`` for
|
|
||||||
mole fractions or ``Y`` for mass fractions.
|
|
||||||
:param mode:
|
|
||||||
Mode *h5py* uses to open the output file {'a' to read/write if file
|
|
||||||
exists, create otherwise (default); 'w' to create file, truncate if
|
|
||||||
exists; 'r+' to read/write, file must exist}.
|
|
||||||
:param description:
|
|
||||||
Custom comment describing the dataset to be stored.
|
|
||||||
:param compression:
|
|
||||||
Pre-defined *h5py* compression filters {None, 'gzip', 'lzf', 'szip'}
|
|
||||||
used for data compression.
|
|
||||||
:param compression_opts:
|
|
||||||
Options for the *h5py* compression filter; for 'gzip', this
|
|
||||||
corresponds to the compression level {None, 0-9}.
|
|
||||||
:param quiet:
|
|
||||||
Suppress message confirming successful file output.
|
|
||||||
:param normalize:
|
|
||||||
Boolean flag to indicate whether the mole/mass fractions should
|
|
||||||
be normalized (default is ``True``)
|
|
||||||
|
|
||||||
Additional arguments (that is, ``*args`` and ``**kwargs``) are passed on to
|
|
||||||
`SolutionArray.collect_data`. The method exports data using
|
|
||||||
`SolutionArray.write_hdf` via `to_solution_array` and requires a working
|
|
||||||
installation of *h5py* (``h5py`` can be installed using pip or conda).
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; use `save` instead. Note that
|
|
||||||
the call is redirected to `save` in order to prevent the creation of a file
|
|
||||||
with deprecated HDF format.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.write_hdf: To be removed after Cantera 3.0; use "
|
|
||||||
"'save' instead.\nNote that the call is redirected to 'save' in order to "
|
|
||||||
"prevent the creation of a file with deprecated HDF format.",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
self.save(filename, name=group, description=description,
|
|
||||||
compression=compression_opts)
|
|
||||||
|
|
||||||
def read_hdf(self, filename, group=None, restore_boundaries=True, normalize=True):
|
|
||||||
"""
|
|
||||||
Restore the solution vector from a HDF container file.
|
|
||||||
|
|
||||||
:param filename:
|
|
||||||
HDF container file containing data to be restored
|
|
||||||
:param group:
|
|
||||||
String identifying the HDF group containing the data
|
|
||||||
:param restore_boundaries:
|
|
||||||
Boolean flag to indicate whether boundaries should be restored
|
|
||||||
(default is ``True``)
|
|
||||||
:param normalize:
|
|
||||||
Boolean flag to indicate whether the mole/mass fractions should
|
|
||||||
be normalized (default is ``True``)
|
|
||||||
|
|
||||||
The method imports data using `SolutionArray.read_hdf` via
|
|
||||||
`from_array` and requires a working installation of *h5py*
|
|
||||||
(``h5py`` can be installed using pip or conda).
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Method to be removed after Cantera 3.0; superseded by `restore`.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.read_hdf: To be removed after Cantera 3.0; use "
|
|
||||||
"'restore' instead.", DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
if restore_boundaries:
|
|
||||||
domains = range(3)
|
|
||||||
else:
|
|
||||||
domains = [1]
|
|
||||||
|
|
||||||
for d in domains:
|
|
||||||
arr = SolutionArray(self.phase(d), extra=self.other_components(d))
|
|
||||||
meta = arr.read_hdf(filename, group=group,
|
|
||||||
subgroup=self.domains[d].name, normalize=normalize)
|
|
||||||
self.from_solution_array(arr, domain=d)
|
|
||||||
|
|
||||||
self.settings = meta
|
|
||||||
|
|
||||||
return meta
|
|
||||||
|
|
||||||
@property
|
|
||||||
def settings(self):
|
|
||||||
"""
|
|
||||||
Return a dictionary listing simulation settings
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0. The getter is replaceable by
|
|
||||||
`Domain1D.settings`; for the setter, use setters for individual settings.
|
|
||||||
"""
|
|
||||||
warnings.warn("FlameBase.settings: to be removed after Cantera 3.0. Access "
|
|
||||||
"settings from domains instead.", DeprecationWarning, stacklevel=2)
|
|
||||||
out = {'Sim1D_type': type(self).__name__}
|
|
||||||
out['transport_model'] = self.transport_model
|
|
||||||
out['energy_enabled'] = self.energy_enabled
|
|
||||||
out['soret_enabled'] = self.soret_enabled
|
|
||||||
out['radiation_enabled'] = self.radiation_enabled
|
|
||||||
out['fixed_temperature'] = self.fixed_temperature
|
|
||||||
out.update(self.get_refine_criteria())
|
|
||||||
out['max_time_step_count'] = self.max_time_step_count
|
|
||||||
out['max_grid_points'] = self.get_max_grid_points(self.flame)
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
@settings.setter
|
|
||||||
def settings(self, s):
|
|
||||||
warnings.warn("FlameBase.settings: To be removed after Cantera 3.0. Use "
|
|
||||||
"individual setters instead.", DeprecationWarning, stacklevel=2)
|
|
||||||
# simple setters
|
|
||||||
attr = {'transport_model',
|
|
||||||
'energy_enabled', 'soret_enabled', 'radiation_enabled',
|
|
||||||
'fixed_temperature',
|
|
||||||
'max_time_step_count', 'max_grid_points'}
|
|
||||||
attr = attr & set(s.keys())
|
|
||||||
for key in attr:
|
|
||||||
setattr(self, key, s[key])
|
|
||||||
|
|
||||||
# refine criteria
|
|
||||||
refine = {k: v for k, v in s.items()
|
|
||||||
if k in ['ratio', 'slope', 'curve', 'prune']}
|
|
||||||
if refine:
|
|
||||||
self.set_refine_criteria(**refine)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def electric_field_enabled(self):
|
def electric_field_enabled(self):
|
||||||
""" Get/Set whether or not to solve the Poisson's equation."""
|
""" Get/Set whether or not to solve the Poisson's equation."""
|
||||||
@ -842,7 +519,6 @@ for _attr in ['forward_rates_of_progress', 'reverse_rates_of_progress', 'net_rat
|
|||||||
class FreeFlame(FlameBase):
|
class FreeFlame(FlameBase):
|
||||||
"""A freely-propagating flat flame."""
|
"""A freely-propagating flat flame."""
|
||||||
__slots__ = ('inlet', 'flame', 'outlet')
|
__slots__ = ('inlet', 'flame', 'outlet')
|
||||||
_other = ('grid', 'velocity')
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
def __init__(self, gas, grid=None, width=None):
|
||||||
"""
|
"""
|
||||||
@ -1033,27 +709,9 @@ class FreeFlame(FlameBase):
|
|||||||
return self.solve_adjoint(perturb, self.gas.n_reactions, dgdx) / Su0
|
return self.solve_adjoint(perturb, self.gas.n_reactions, dgdx) / Su0
|
||||||
|
|
||||||
|
|
||||||
class IonFreeFlame(FreeFlame):
|
|
||||||
"""A freely-propagating flame with ionized gas.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0; absorbed by `FreeFlame`.
|
|
||||||
"""
|
|
||||||
__slots__ = ('inlet', 'flame', 'outlet')
|
|
||||||
_other = ('grid', 'velocity', 'eField') # only used by deprecated methods
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
|
||||||
warnings.warn(
|
|
||||||
"'IonFreeFlame' is deprecated and will be removed after Cantera 3.0;",
|
|
||||||
"replaceable by 'FreeFlame'.", DeprecationWarning, stacklevel=2)
|
|
||||||
super().__init__(gas, grid, width)
|
|
||||||
|
|
||||||
|
|
||||||
class BurnerFlame(FlameBase):
|
class BurnerFlame(FlameBase):
|
||||||
"""A burner-stabilized flat flame."""
|
"""A burner-stabilized flat flame."""
|
||||||
__slots__ = ('burner', 'flame', 'outlet')
|
__slots__ = ('burner', 'flame', 'outlet')
|
||||||
_other = ('grid', 'velocity')
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
def __init__(self, gas, grid=None, width=None):
|
||||||
"""
|
"""
|
||||||
@ -1187,27 +845,9 @@ class BurnerFlame(FlameBase):
|
|||||||
self.set_steady_callback(original_callback)
|
self.set_steady_callback(original_callback)
|
||||||
|
|
||||||
|
|
||||||
class IonBurnerFlame(BurnerFlame):
|
|
||||||
"""A burner-stabilized flat flame with ionized gas.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0; absorbed by `BurnerFlame`.
|
|
||||||
"""
|
|
||||||
__slots__ = ('burner', 'flame', 'outlet')
|
|
||||||
_other = ('grid', 'velocity', 'eField') # only used by deprecated methods
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
|
||||||
warnings.warn(
|
|
||||||
"'IonBurnerFlame' is deprecated and will be removed after Cantera 3.0; ",
|
|
||||||
"replaceable by 'BurnerFlame'.", DeprecationWarning, stacklevel=2)
|
|
||||||
super().__init__(gas, grid, width)
|
|
||||||
|
|
||||||
|
|
||||||
class CounterflowDiffusionFlame(FlameBase):
|
class CounterflowDiffusionFlame(FlameBase):
|
||||||
""" A counterflow diffusion flame """
|
""" A counterflow diffusion flame """
|
||||||
__slots__ = ('fuel_inlet', 'flame', 'oxidizer_inlet')
|
__slots__ = ('fuel_inlet', 'flame', 'oxidizer_inlet')
|
||||||
_other = ('grid', 'velocity', 'spread_rate', 'lambda')
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
def __init__(self, gas, grid=None, width=None):
|
||||||
"""
|
"""
|
||||||
@ -1536,7 +1176,6 @@ class CounterflowDiffusionFlame(FlameBase):
|
|||||||
class ImpingingJet(FlameBase):
|
class ImpingingJet(FlameBase):
|
||||||
"""An axisymmetric flow impinging on a surface at normal incidence."""
|
"""An axisymmetric flow impinging on a surface at normal incidence."""
|
||||||
__slots__ = ('inlet', 'flame', 'surface')
|
__slots__ = ('inlet', 'flame', 'surface')
|
||||||
_other = ('grid', 'velocity', 'spread_rate', 'lambda')
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None, surface=None):
|
def __init__(self, gas, grid=None, width=None, surface=None):
|
||||||
"""
|
"""
|
||||||
@ -1625,7 +1264,6 @@ class ImpingingJet(FlameBase):
|
|||||||
class CounterflowPremixedFlame(FlameBase):
|
class CounterflowPremixedFlame(FlameBase):
|
||||||
""" A premixed counterflow flame """
|
""" A premixed counterflow flame """
|
||||||
__slots__ = ('reactants', 'flame', 'products')
|
__slots__ = ('reactants', 'flame', 'products')
|
||||||
_other = ('grid', 'velocity', 'spread_rate', 'lambda')
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
def __init__(self, gas, grid=None, width=None):
|
||||||
"""
|
"""
|
||||||
@ -1727,7 +1365,6 @@ class CounterflowTwinPremixedFlame(FlameBase):
|
|||||||
shooting into each other.
|
shooting into each other.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('reactants', 'flame', 'products')
|
__slots__ = ('reactants', 'flame', 'products')
|
||||||
_other = ('grid', 'velocity', 'spread_rate', 'lambda')
|
|
||||||
|
|
||||||
def __init__(self, gas, grid=None, width=None):
|
def __init__(self, gas, grid=None, width=None):
|
||||||
"""
|
"""
|
||||||
|
@ -1322,12 +1322,7 @@ cdef class Reaction:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __cinit__(self, reactants=None, products=None, rate=None, *,
|
def __cinit__(self, reactants=None, products=None, rate=None, *,
|
||||||
equation=None, init=True, efficiencies=None,
|
equation=None, init=True, third_body=None):
|
||||||
Kinetics kinetics=None, third_body=None):
|
|
||||||
if kinetics:
|
|
||||||
warnings.warn("Reaction: Parameter 'kinetics' is no longer used and will "
|
|
||||||
"be removed after Cantera 3.0.", DeprecationWarning)
|
|
||||||
|
|
||||||
if not init:
|
if not init:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -1364,13 +1359,6 @@ cdef class Reaction:
|
|||||||
_third_body = third_body
|
_third_body = third_body
|
||||||
elif isinstance(third_body, str):
|
elif isinstance(third_body, str):
|
||||||
_third_body = ThirdBody(third_body)
|
_third_body = ThirdBody(third_body)
|
||||||
elif efficiencies:
|
|
||||||
warnings.warn(
|
|
||||||
"Reaction: Argument 'efficiencies' is deprecated and will be removed "
|
|
||||||
"after Cantera 3.0. Use ThirdBody instead.", DeprecationWarning)
|
|
||||||
third_body = "M"
|
|
||||||
_third_body = ThirdBody(third_body)
|
|
||||||
_third_body.efficiencies = efficiencies
|
|
||||||
|
|
||||||
if reactants and products:
|
if reactants and products:
|
||||||
# create from reactant and product compositions
|
# create from reactant and product compositions
|
||||||
@ -1521,19 +1509,10 @@ cdef class Reaction:
|
|||||||
``{'CH4':1, 'OH':1}``, or as a composition string, for example
|
``{'CH4':1, 'OH':1}``, or as a composition string, for example
|
||||||
``'CH4:1, OH:1'``.
|
``'CH4:1, OH:1'``.
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
.. versionchanged:: 3.1 This is a read-only property
|
||||||
|
|
||||||
Setter for reactants is deprecated and will be removed after Cantera 3.0.
|
|
||||||
Use constructor instead.
|
|
||||||
"""
|
"""
|
||||||
def __get__(self):
|
def __get__(self):
|
||||||
return comp_map_to_dict(self.reaction.reactants)
|
return comp_map_to_dict(self.reaction.reactants)
|
||||||
def __set__(self, reactants):
|
|
||||||
warnings.warn(
|
|
||||||
"'Reaction.reactants' setter is deprecated and will be removed after "
|
|
||||||
"Cantera 3.0.\nInstantiate using constructor instead.",
|
|
||||||
DeprecationWarning)
|
|
||||||
self.reaction.reactants = comp_map(reactants)
|
|
||||||
|
|
||||||
property products:
|
property products:
|
||||||
"""
|
"""
|
||||||
@ -1542,19 +1521,10 @@ cdef class Reaction:
|
|||||||
``{'CH3':1, 'H2O':1}``, or as a composition string, for example
|
``{'CH3':1, 'H2O':1}``, or as a composition string, for example
|
||||||
``'CH3:1, H2O:1'``.
|
``'CH3:1, H2O:1'``.
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
.. versionchanged:: 3.1 This is a read-only property
|
||||||
|
|
||||||
Setter for products is deprecated and will be removed after Cantera 3.0.
|
|
||||||
Use constructor instead.
|
|
||||||
"""
|
"""
|
||||||
def __get__(self):
|
def __get__(self):
|
||||||
return comp_map_to_dict(self.reaction.products)
|
return comp_map_to_dict(self.reaction.products)
|
||||||
def __set__(self, products):
|
|
||||||
warnings.warn(
|
|
||||||
"'Reaction.products' setter is deprecated and will be removed after "
|
|
||||||
"Cantera 3.0.\nInstantiate using constructor instead.",
|
|
||||||
DeprecationWarning)
|
|
||||||
self.reaction.products = comp_map(products)
|
|
||||||
|
|
||||||
def __contains__(self, species):
|
def __contains__(self, species):
|
||||||
return species in self.reactants or species in self.products
|
return species in self.reactants or species in self.products
|
||||||
@ -1703,73 +1673,6 @@ cdef class Reaction:
|
|||||||
return ThirdBody.wrap(self.reaction.thirdBody()).name
|
return ThirdBody.wrap(self.reaction.thirdBody()).name
|
||||||
return None
|
return None
|
||||||
|
|
||||||
property efficiencies:
|
|
||||||
"""
|
|
||||||
Get/Set a `dict` defining non-default third-body efficiencies for this reaction,
|
|
||||||
where the keys are the species names and the values are the efficiencies.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0. Access via `third_body` property and
|
|
||||||
`ThirdBody` object instead.
|
|
||||||
"""
|
|
||||||
def __get__(self):
|
|
||||||
warnings.warn(
|
|
||||||
"Reaction.efficiencies: Property is deprecated and will be removed "
|
|
||||||
"after Cantera 3.0. Access via ThirdBody instead.", DeprecationWarning)
|
|
||||||
if self.third_body is None:
|
|
||||||
raise ValueError("Reaction does not involve third body collider")
|
|
||||||
return self.third_body.efficiencies
|
|
||||||
def __set__(self, eff):
|
|
||||||
warnings.warn(
|
|
||||||
"Reaction.efficiencies: Property is deprecated and will be removed "
|
|
||||||
"after Cantera 3.0. Access via ThirdBody instead.", DeprecationWarning)
|
|
||||||
if self.third_body is None:
|
|
||||||
raise ValueError("Reaction does not involve third body collider")
|
|
||||||
self.third_body.efficiencies = comp_map(eff)
|
|
||||||
|
|
||||||
property default_efficiency:
|
|
||||||
"""
|
|
||||||
Get/Set the default third-body efficiency for this reaction, used for species
|
|
||||||
not in `efficiencies`.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0. Access via `third_body` property and
|
|
||||||
`ThirdBody` object instead.
|
|
||||||
"""
|
|
||||||
def __get__(self):
|
|
||||||
warnings.warn(
|
|
||||||
"Reaction.default_efficiency: Property is deprecated and will be "
|
|
||||||
"removed after Cantera 3.0. Use ThirdBody instead.", DeprecationWarning)
|
|
||||||
if self.third_body is None:
|
|
||||||
raise ValueError("Reaction does not involve third body collider")
|
|
||||||
return self.third_body.default_efficiency
|
|
||||||
def __set__(self, default_eff):
|
|
||||||
warnings.warn(
|
|
||||||
"Reaction.default_efficiency: Property is deprecated and will be "
|
|
||||||
"removed after Cantera 3.0. Use ThirdBody instead.", DeprecationWarning)
|
|
||||||
if self.third_body is None:
|
|
||||||
raise ValueError("Reaction does not involve third body collider")
|
|
||||||
self.third_body.default_efficiency = default_eff
|
|
||||||
|
|
||||||
def efficiency(self, species):
|
|
||||||
"""
|
|
||||||
Get the efficiency of the third body named ``species`` considering both
|
|
||||||
the default efficiency and species-specific efficiencies.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0. Access via `third_body` property and
|
|
||||||
`ThirdBody` object instead.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"Reaction.efficiency: Method is deprecated and will be removed after "
|
|
||||||
"Cantera 3.0. Use ThirdBody instead.", DeprecationWarning)
|
|
||||||
if self.third_body is None:
|
|
||||||
raise ValueError("Reaction does not involve third body collider")
|
|
||||||
return self.third_body.efficiency(stringify(species))
|
|
||||||
|
|
||||||
|
|
||||||
cdef class Arrhenius:
|
cdef class Arrhenius:
|
||||||
r"""
|
r"""
|
||||||
@ -1837,99 +1740,3 @@ cdef copyArrhenius(CxxArrheniusRate* rate):
|
|||||||
r = Arrhenius(rate.preExponentialFactor(), rate.temperatureExponent(),
|
r = Arrhenius(rate.preExponentialFactor(), rate.temperatureExponent(),
|
||||||
rate.activationEnergy())
|
rate.activationEnergy())
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
cdef class ThreeBodyReaction(Reaction):
|
|
||||||
"""
|
|
||||||
A reaction with a non-reacting third body "M" that acts to add or remove
|
|
||||||
energy from the reacting species.
|
|
||||||
|
|
||||||
An example for the definition of an `ThreeBodyReaction` object is given as::
|
|
||||||
|
|
||||||
rxn = ThreeBodyReaction(
|
|
||||||
equation="2 O + M <=> O2 + M",
|
|
||||||
rate={"A": 1.2e+17, "b": -1.0, "Ea": 0.0},
|
|
||||||
efficiencies={"H2": 2.4, "H2O": 15.4, "AR": 0.83},
|
|
||||||
kinetics=gas)
|
|
||||||
|
|
||||||
The YAML description corresponding to this reaction is::
|
|
||||||
|
|
||||||
equation: 2 O + M <=> O2 + M
|
|
||||||
type: three-body
|
|
||||||
rate-constant: {A: 1.2e+17 cm^6/mol^2/s, b: -1.0, Ea: 0.0 cal/mol}
|
|
||||||
efficiencies: {H2: 2.4, H2O: 15.4, AR: 0.83}
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0. Absorbed by `Reaction`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("ThreeBodyReaction: Class to be removed after Cantera 3.0; "
|
|
||||||
"no specialization necessary.", DeprecationWarning)
|
|
||||||
|
|
||||||
|
|
||||||
cdef class FalloffReaction(Reaction):
|
|
||||||
"""
|
|
||||||
A reaction that is first-order in [M] at low pressure, like a third-body
|
|
||||||
reaction, but zeroth-order in [M] as pressure increases.
|
|
||||||
|
|
||||||
An example for the definition of a `FalloffReaction` object is given as::
|
|
||||||
|
|
||||||
rxn = FalloffReaction(
|
|
||||||
equation="2 OH (+ M) <=> H2O2 (+ M)",
|
|
||||||
rate=ct.TroeRate(low=ct.Arrhenius(2.3e+12, -0.9, -7112800.0),
|
|
||||||
high=ct.Arrhenius(7.4e+10, -0.37, 0),
|
|
||||||
falloff_coeffs=[0.7346, 94.0, 1756.0, 5182.0]),
|
|
||||||
efficiencies={"AR": 0.7, "H2": 2.0, "H2O": 6.0},
|
|
||||||
kinetics=gas)
|
|
||||||
|
|
||||||
The YAML description corresponding to this reaction is::
|
|
||||||
|
|
||||||
equation: 2 OH (+ M) <=> H2O2 (+ M) # Reaction 3
|
|
||||||
type: falloff
|
|
||||||
low-P-rate-constant: {A: 2.3e+12, b: -0.9, Ea: -1700.0 cal/mol}
|
|
||||||
high-P-rate-constant: {A: 7.4e+10, b: -0.37, Ea: 0.0 cal/mol}
|
|
||||||
Troe: {A: 0.7346, T3: 94.0, T1: 1756.0, T2: 5182.0}
|
|
||||||
efficiencies: {AR: 0.7, H2: 2.0, H2O: 6.0}
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0. Absorbed by `Reaction`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("FalloffReaction: Class to be removed after Cantera 3.0; "
|
|
||||||
"no specialization necessary.", DeprecationWarning)
|
|
||||||
|
|
||||||
cdef class ChemicallyActivatedReaction(FalloffReaction):
|
|
||||||
"""
|
|
||||||
A reaction where the rate decreases as pressure increases due to collisional
|
|
||||||
stabilization of a reaction intermediate. Like a `FalloffReaction`, except
|
|
||||||
that the forward rate constant is written as being proportional to the low-
|
|
||||||
pressure rate constant.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("ChemicallyActivatedReaction: Class to be removed after Cantera "
|
|
||||||
"3.0; no specialization necessary.", DeprecationWarning)
|
|
||||||
|
|
||||||
cdef class CustomReaction(Reaction):
|
|
||||||
"""
|
|
||||||
A reaction which follows mass-action kinetics with a custom reaction rate.
|
|
||||||
|
|
||||||
An example for the definition of a `CustomReaction` object is given as::
|
|
||||||
|
|
||||||
rxn = CustomReaction(
|
|
||||||
equation="H2 + O <=> H + OH",
|
|
||||||
rate=lambda T: 38.7 * T**2.7 * exp(-3150.15428/T),
|
|
||||||
kinetics=gas)
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Class to be removed after Cantera 3.0. Absorbed by `Reaction`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("CustomReaction: Class to be removed after Cantera 3.0; no "
|
|
||||||
"specialization necessary.", DeprecationWarning)
|
|
||||||
|
@ -646,25 +646,6 @@ cdef class ExtensibleReactor(Reactor):
|
|||||||
def __set__(self, n):
|
def __set__(self, n):
|
||||||
self.accessor.setNEq(n)
|
self.accessor.setNEq(n)
|
||||||
|
|
||||||
property vdot:
|
|
||||||
"""
|
|
||||||
Get/Set the net rate of volume change (for example, from moving walls) [m^3/s]
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed in Cantera 3.0; renamed to `expansion_rate`.
|
|
||||||
"""
|
|
||||||
def __get__(self):
|
|
||||||
warnings.warn(
|
|
||||||
"ExtensibleReactor.vdot: To be removed in Cantera 3.0; "
|
|
||||||
"renamed to 'expansion_rate'.", DeprecationWarning)
|
|
||||||
return self.accessor.expansionRate()
|
|
||||||
def __set__(self, vdot):
|
|
||||||
warnings.warn(
|
|
||||||
"ExtensibleReactor.vdot: To be removed in Cantera 3.0; "
|
|
||||||
"renamed to 'expansion_rate'.", DeprecationWarning)
|
|
||||||
self.accessor.setExpansionRate(vdot)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def expansion_rate(self):
|
def expansion_rate(self):
|
||||||
"""
|
"""
|
||||||
@ -678,25 +659,6 @@ cdef class ExtensibleReactor(Reactor):
|
|||||||
def expansion_rate(self, vdot):
|
def expansion_rate(self, vdot):
|
||||||
self.accessor.setExpansionRate(vdot)
|
self.accessor.setExpansionRate(vdot)
|
||||||
|
|
||||||
property qdot:
|
|
||||||
"""
|
|
||||||
Get/Set the net heat transfer rate (for example, through walls) [W]
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed in Cantera 3.0; renamed to `heat_rate`.
|
|
||||||
"""
|
|
||||||
def __get__(self):
|
|
||||||
warnings.warn(
|
|
||||||
"ExtensibleReactor.qdot: To be removed in Cantera 3.0; "
|
|
||||||
"renamed to 'heat_rate'.", DeprecationWarning)
|
|
||||||
return self.accessor.heatRate()
|
|
||||||
def __set__(self, qdot):
|
|
||||||
warnings.warn(
|
|
||||||
"ExtensibleReactor.qdot: To be removed in Cantera 3.0; "
|
|
||||||
"renamed to 'heat_rate'.", DeprecationWarning)
|
|
||||||
self.accessor.setHeatRate(qdot)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def heat_rate(self):
|
def heat_rate(self):
|
||||||
"""
|
"""
|
||||||
@ -963,18 +925,6 @@ cdef class WallBase:
|
|||||||
"""
|
"""
|
||||||
return self.wall.expansionRate()
|
return self.wall.expansionRate()
|
||||||
|
|
||||||
def vdot(self, double t):
|
|
||||||
"""
|
|
||||||
The rate of volumetric change [m^3/s] associated with the wall
|
|
||||||
at time ``t``. A positive value corresponds to the left-hand reactor
|
|
||||||
volume increasing, and the right-hand reactor volume decreasing.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0; replaceable by ``expansion_rate``.
|
|
||||||
"""
|
|
||||||
return self.wall.vdot(t)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def heat_rate(self):
|
def heat_rate(self):
|
||||||
"""
|
"""
|
||||||
@ -986,18 +936,6 @@ cdef class WallBase:
|
|||||||
"""
|
"""
|
||||||
return self.wall.heatRate()
|
return self.wall.heatRate()
|
||||||
|
|
||||||
def qdot(self, double t):
|
|
||||||
"""
|
|
||||||
Total heat flux [W] through the wall at time ``t``. A positive value
|
|
||||||
corresponds to heat flowing from the left-hand reactor to the
|
|
||||||
right-hand one.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0; replaceable by ``heat_rate``.
|
|
||||||
"""
|
|
||||||
return self.wall.Q(t)
|
|
||||||
|
|
||||||
|
|
||||||
cdef class Wall(WallBase):
|
cdef class Wall(WallBase):
|
||||||
r"""
|
r"""
|
||||||
@ -1073,20 +1011,6 @@ cdef class Wall(WallBase):
|
|||||||
self._velocity_func = f
|
self._velocity_func = f
|
||||||
(<CxxWall*>(self.wall)).setVelocity(f.func)
|
(<CxxWall*>(self.wall)).setVelocity(f.func)
|
||||||
|
|
||||||
def set_velocity(self, v):
|
|
||||||
"""
|
|
||||||
The wall velocity [m/s]. May be either a constant or an arbitrary
|
|
||||||
function of time. See `Func1`.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Replaced by the ``velocity`` property.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"Wall.set_velocity: To be removed after Cantera 3.0; replaced by property "
|
|
||||||
"'velocity'.", DeprecationWarning)
|
|
||||||
self.velocity = v
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def heat_flux(self):
|
def heat_flux(self):
|
||||||
"""
|
"""
|
||||||
@ -1108,20 +1032,6 @@ cdef class Wall(WallBase):
|
|||||||
self._heat_flux_func = f
|
self._heat_flux_func = f
|
||||||
(<CxxWall*>self.wall).setHeatFlux(f.func)
|
(<CxxWall*>self.wall).setHeatFlux(f.func)
|
||||||
|
|
||||||
def set_heat_flux(self, q):
|
|
||||||
"""
|
|
||||||
Heat flux [W/m^2] across the wall. May be either a constant or
|
|
||||||
an arbitrary function of time. See `Func1`.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
Replaced by the ``heat_flux`` property.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"Wall.set_heat_flux: To be removed after Cantera 3.0; replaced by property "
|
|
||||||
"'heat_flux'.", DeprecationWarning)
|
|
||||||
self.heat_flux = q
|
|
||||||
|
|
||||||
|
|
||||||
cdef class FlowDevice:
|
cdef class FlowDevice:
|
||||||
"""
|
"""
|
||||||
@ -1205,26 +1115,6 @@ cdef class FlowDevice:
|
|||||||
self._rate_func = f
|
self._rate_func = f
|
||||||
self.dev.setPressureFunction(f.func)
|
self.dev.setPressureFunction(f.func)
|
||||||
|
|
||||||
def set_pressure_function(self, k):
|
|
||||||
r"""
|
|
||||||
Set the relationship between mass flow rate and the pressure drop across a
|
|
||||||
flow device. The mass flow rate [kg/s] is calculated given the pressure
|
|
||||||
drop [Pa] and a coefficient set by a flow device specific function.
|
|
||||||
The calculation of mass flow rate depends to the flow device.
|
|
||||||
|
|
||||||
>>> F = FlowDevice(res1, reactor1)
|
|
||||||
>>> F.set_pressure_function(lambda dP: dP**2)
|
|
||||||
|
|
||||||
where FlowDevice is either a Valve or PressureController object.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
To be removed after Cantera 3.0. Use property ``pressure_function`` instead.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"FlowDevice.set_pressure_function: To be removed after Cantera 3.0; "
|
|
||||||
"replaced by 'pressure_function'.", DeprecationWarning)
|
|
||||||
self.pressure_function = k
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def time_function(self):
|
def time_function(self):
|
||||||
r"""
|
r"""
|
||||||
@ -1252,25 +1142,6 @@ cdef class FlowDevice:
|
|||||||
self._time_func = g
|
self._time_func = g
|
||||||
self.dev.setTimeFunction(g.func)
|
self.dev.setTimeFunction(g.func)
|
||||||
|
|
||||||
def set_time_function(self, k):
|
|
||||||
r"""
|
|
||||||
Set the time dependence of a flow device. The mass flow rate [kg/s] is
|
|
||||||
calculated for a flow device, and multiplied by a function of time.
|
|
||||||
The calculation of mass flow rate depends to the flow device.
|
|
||||||
|
|
||||||
>>> F = FlowDevice(res1, reactor1)
|
|
||||||
>>> F.set_time_function(lambda t: exp(-10 * (t - 0.5)**2))
|
|
||||||
|
|
||||||
where FlowDevice is either a Valve or MassFlowController object.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
To be removed after Cantera 3.0. Use property ``time_function`` instead.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"FlowDevice.set_time_function: To be removed after Cantera 3.0; "
|
|
||||||
"replaced by 'time_function'.", DeprecationWarning)
|
|
||||||
self.time_function = k
|
|
||||||
|
|
||||||
|
|
||||||
cdef class MassFlowController(FlowDevice):
|
cdef class MassFlowController(FlowDevice):
|
||||||
r"""
|
r"""
|
||||||
@ -1452,20 +1323,6 @@ cdef class PressureController(FlowDevice):
|
|||||||
def primary(self, FlowDevice d):
|
def primary(self, FlowDevice d):
|
||||||
(<CxxPressureController*>self.dev).setPrimary(d.dev)
|
(<CxxPressureController*>self.dev).setPrimary(d.dev)
|
||||||
|
|
||||||
def set_master(self, FlowDevice d):
|
|
||||||
"""
|
|
||||||
Set the "master" `FlowDevice` used to compute this device's mass flow
|
|
||||||
rate.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
|
|
||||||
To be removed after Cantera 3.0; replaced by property ``primary``.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"PressureController.set_master: To be removed after Cantera 3.0; "
|
|
||||||
"replaced by 'primary'.", DeprecationWarning)
|
|
||||||
self.primary = d
|
|
||||||
|
|
||||||
|
|
||||||
cdef class ReactorNet:
|
cdef class ReactorNet:
|
||||||
"""
|
"""
|
||||||
@ -1556,19 +1413,6 @@ cdef class ReactorNet:
|
|||||||
def initial_time(self, double t):
|
def initial_time(self, double t):
|
||||||
self.net.setInitialTime(t)
|
self.net.setInitialTime(t)
|
||||||
|
|
||||||
def set_initial_time(self, double t):
|
|
||||||
"""
|
|
||||||
Set the initial time. Restarts integration from this time using the
|
|
||||||
current state as the initial condition. Default: 0.0 s.
|
|
||||||
|
|
||||||
.. deprecated:: 3.0
|
|
||||||
To be removed after Cantera 3.0. Use property ``initial_time`` instead.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"ReactorNet.set_initial_time: To be removed after Cantera 3.0. "
|
|
||||||
"Use property 'initial_time' instead.", DeprecationWarning)
|
|
||||||
self.initial_time = t
|
|
||||||
|
|
||||||
property max_time_step:
|
property max_time_step:
|
||||||
"""
|
"""
|
||||||
Get/set the maximum time step *t* [s] that the integrator is
|
Get/set the maximum time step *t* [s] that the integrator is
|
||||||
|
@ -54,26 +54,6 @@ cdef class _SolutionBase:
|
|||||||
|
|
||||||
def _cinit(self, infile="", name="", adjacent=(), origin=None, yaml=None,
|
def _cinit(self, infile="", name="", adjacent=(), origin=None, yaml=None,
|
||||||
thermo=None, species=(), kinetics=None, reactions=(), **kwargs):
|
thermo=None, species=(), kinetics=None, reactions=(), **kwargs):
|
||||||
|
|
||||||
if 'phaseid' in kwargs:
|
|
||||||
if name is not '':
|
|
||||||
raise AttributeError('duplicate specification of phase name')
|
|
||||||
|
|
||||||
warnings.warn(
|
|
||||||
"_SolutionBase: Support for keyword 'phaseid' to be removed after "
|
|
||||||
"Cantera 3.0. Replaceable by keyword 'name'.", DeprecationWarning)
|
|
||||||
name = kwargs['phaseid']
|
|
||||||
|
|
||||||
if 'phases' in kwargs:
|
|
||||||
if len(adjacent)>0:
|
|
||||||
raise AttributeError(
|
|
||||||
'duplicate specification of adjacent phases')
|
|
||||||
|
|
||||||
warnings.warn(
|
|
||||||
"_SolutionBase: Support for keyword 'phases' to be removed after "
|
|
||||||
"Cantera 3.0. Replaceable by keyword 'adjacent'.", DeprecationWarning)
|
|
||||||
adjacent = kwargs['phases']
|
|
||||||
|
|
||||||
# Shallow copy of an existing Solution (for slicing support)
|
# Shallow copy of an existing Solution (for slicing support)
|
||||||
cdef _SolutionBase other
|
cdef _SolutionBase other
|
||||||
if origin is not None:
|
if origin is not None:
|
||||||
|
@ -13,12 +13,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
from cantera.composite import _pandas
|
||||||
ct.composite._import_h5py()
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
from cantera.composite import _pandas, _h5py
|
|
||||||
from . import utilities
|
from . import utilities
|
||||||
|
|
||||||
|
|
||||||
@ -476,58 +471,6 @@ class TestSolutionArrayIO(utilities.CanteraTest):
|
|||||||
for key, value in a.meta.items():
|
for key, value in a.meta.items():
|
||||||
assert b.meta[key] == value
|
assert b.meta[key] == value
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
def test_write_csv_legacy(self):
|
|
||||||
states = ct.SolutionArray(self.gas, 7)
|
|
||||||
states.TPX = np.linspace(300, 1000, 7), 2e5, 'H2:0.5, O2:0.4'
|
|
||||||
states.equilibrate('HP')
|
|
||||||
|
|
||||||
outfile = self.test_work_path / "solutionarray.csv"
|
|
||||||
states.write_csv(outfile)
|
|
||||||
|
|
||||||
data = np.genfromtxt(outfile, names=True, delimiter=',')
|
|
||||||
self.assertEqual(len(data), 7)
|
|
||||||
self.assertEqual(len(data.dtype), self.gas.n_species + 2)
|
|
||||||
self.assertIn('Y_H2', data.dtype.fields)
|
|
||||||
|
|
||||||
b = ct.SolutionArray(self.gas)
|
|
||||||
b.read_csv(outfile)
|
|
||||||
self.check_arrays(states, b)
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
def test_write_csv_single_row(self):
|
|
||||||
gas = ct.Solution("gri30.yaml")
|
|
||||||
states = ct.SolutionArray(gas)
|
|
||||||
states.append(T=300., P=ct.one_atm, X="CH4:0.5, O2:0.4")
|
|
||||||
states.equilibrate("HP")
|
|
||||||
|
|
||||||
outfile = self.test_work_path / "solutionarray.csv"
|
|
||||||
states.write_csv(outfile)
|
|
||||||
|
|
||||||
b = ct.SolutionArray(gas)
|
|
||||||
b.read_csv(outfile)
|
|
||||||
self.check_arrays(states, b)
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
def test_write_csv_str_column(self):
|
|
||||||
states = ct.SolutionArray(self.gas, 3, extra={'spam': 'eggs'})
|
|
||||||
|
|
||||||
outfile = self.test_work_path / "solutionarray.csv"
|
|
||||||
states.write_csv(outfile)
|
|
||||||
|
|
||||||
b = ct.SolutionArray(self.gas, extra={'spam'})
|
|
||||||
b.read_csv(outfile)
|
|
||||||
self.assertEqual(list(states.spam), list(b.spam))
|
|
||||||
self.check_arrays(states, b)
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
def test_write_csv_multidim_column(self):
|
|
||||||
states = ct.SolutionArray(self.gas, 3, extra={'spam': np.zeros((3, 5,))})
|
|
||||||
|
|
||||||
outfile = self.test_work_path / "solutionarray.csv"
|
|
||||||
with self.assertRaisesRegex(NotImplementedError, 'not supported'):
|
|
||||||
states.write_csv(outfile)
|
|
||||||
|
|
||||||
def test_write_csv(self):
|
def test_write_csv(self):
|
||||||
outfile = self.test_work_path / "solutionarray_new.csv"
|
outfile = self.test_work_path / "solutionarray_new.csv"
|
||||||
outfile.unlink(missing_ok=True)
|
outfile.unlink(missing_ok=True)
|
||||||
@ -718,12 +661,6 @@ class TestLegacyHDF(utilities.CanteraTest):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.gas = ct.Solution('h2o2.yaml', transport_model=None)
|
self.gas = ct.Solution('h2o2.yaml', transport_model=None)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif("h5py" not in ct.hdf_support(), reason="h5py is not installed")
|
|
||||||
def test_legacy_hdf_str_column_h5py(self):
|
|
||||||
self.run_read_legacy_hdf_str_column(legacy=True)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="Unable to read fixed length strings from HDF")
|
@pytest.mark.xfail(reason="Unable to read fixed length strings from HDF")
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
@ -747,61 +684,18 @@ class TestLegacyHDF(utilities.CanteraTest):
|
|||||||
b.restore(infile, "group0")
|
b.restore(infile, "group0")
|
||||||
assert all(arr.spam == b.spam)
|
assert all(arr.spam == b.spam)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif("h5py" not in ct.hdf_support(), reason="h5py is not installed")
|
|
||||||
def test_legacy_hdf_multidim_h5py(self):
|
|
||||||
self.run_read_legacy_hdf_multidim(legacy=True)
|
|
||||||
|
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
||||||
def test_legacy_hdf_multidim(self):
|
def test_legacy_hdf_multidim(self):
|
||||||
self.run_read_legacy_hdf_multidim()
|
|
||||||
|
|
||||||
def run_read_legacy_hdf_multidim(self, legacy=False):
|
|
||||||
# recreate states used to create legacy HDF file
|
# recreate states used to create legacy HDF file
|
||||||
arr = ct.SolutionArray(self.gas, 3, extra={'spam': [[1, 2], [3, 4], [5, 6]]})
|
arr = ct.SolutionArray(self.gas, 3, extra={'spam': [[1, 2], [3, 4], [5, 6]]})
|
||||||
b = ct.SolutionArray(self.gas, extra={'spam'})
|
b = ct.SolutionArray(self.gas, extra={'spam'})
|
||||||
infile = self.test_data_path / f"solutionarray_multi_legacy.h5"
|
infile = self.test_data_path / f"solutionarray_multi_legacy.h5"
|
||||||
|
|
||||||
if legacy:
|
b.restore(infile, "group0")
|
||||||
b.read_hdf(infile)
|
|
||||||
else:
|
|
||||||
b.restore(infile, "group0")
|
|
||||||
self.assertArrayNear(arr.spam, b.spam)
|
self.assertArrayNear(arr.spam, b.spam)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif(ct.hdf_support() != {"native", "h5py"},
|
|
||||||
reason="Both HDF support modes needed")
|
|
||||||
def test_deprecated_write_read_hdf(self):
|
|
||||||
# recreate states used to create legacy HDF file
|
|
||||||
arr = ct.SolutionArray(self.gas, 3, extra={'spam': [[1, 2], [3, 4], [5, 6]]})
|
|
||||||
outfile = self.test_work_path / "solutionarray_deprecated.h5"
|
|
||||||
outfile.unlink(missing_ok=True)
|
|
||||||
|
|
||||||
with pytest.raises(KeyError, match="Missing required parameter 'group'"):
|
|
||||||
arr.write_hdf(outfile, "group0")
|
|
||||||
|
|
||||||
with pytest.warns(DeprecationWarning, match="use 'save' instead"):
|
|
||||||
# New HDF format is written regardless via 'save'
|
|
||||||
arr.write_hdf(outfile, group="group0")
|
|
||||||
|
|
||||||
b = ct.SolutionArray(self.gas)
|
|
||||||
with pytest.raises(IOError, match="use 'restore' instead"):
|
|
||||||
# New HDF format should not be read with 'read_hdf'
|
|
||||||
with pytest.warns(DeprecationWarning, match="use 'restore' instead"):
|
|
||||||
# DeprecationWarning is triggered before IOError is raised
|
|
||||||
b.read_hdf(outfile, group="group0")
|
|
||||||
|
|
||||||
meta = b.restore(outfile, "group0")
|
|
||||||
assert meta["generator"] == "Cantera SolutionArray"
|
|
||||||
self.assertArrayNear(arr.spam, b.spam)
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif("h5py" not in ct.hdf_support(), reason="h5py is not installed")
|
|
||||||
def test_legacy_hdf_h5py(self):
|
|
||||||
self.run_legacy_hdf(legacy=True)
|
|
||||||
|
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
||||||
@ -818,10 +712,7 @@ class TestLegacyHDF(utilities.CanteraTest):
|
|||||||
|
|
||||||
infile = self.test_data_path / f"solutionarray_fancy_legacy.h5"
|
infile = self.test_data_path / f"solutionarray_fancy_legacy.h5"
|
||||||
b = ct.SolutionArray(self.gas)
|
b = ct.SolutionArray(self.gas)
|
||||||
if legacy:
|
attr = b.restore(infile, "group0")
|
||||||
attr = b.read_hdf(infile)
|
|
||||||
else:
|
|
||||||
attr = b.restore(infile, "group0")
|
|
||||||
self.assertArrayNear(states.T, b.T)
|
self.assertArrayNear(states.T, b.T)
|
||||||
self.assertArrayNear(states.P, b.P)
|
self.assertArrayNear(states.P, b.P)
|
||||||
self.assertArrayNear(states.X, b.X)
|
self.assertArrayNear(states.X, b.X)
|
||||||
@ -831,11 +722,6 @@ class TestLegacyHDF(utilities.CanteraTest):
|
|||||||
self.assertEqual(b.meta['hello'], 'world')
|
self.assertEqual(b.meta['hello'], 'world')
|
||||||
self.assertEqual(attr['foobar'], 'spam and eggs')
|
self.assertEqual(attr['foobar'], 'spam and eggs')
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif("h5py" not in ct.hdf_support(), reason="h5py is not installed")
|
|
||||||
def test_read_legacy_hdf_no_norm_h5py(self):
|
|
||||||
self.run_read_legacy_hdf_no_norm(legacy=True)
|
|
||||||
|
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
||||||
@ -858,18 +744,10 @@ class TestLegacyHDF(utilities.CanteraTest):
|
|||||||
self.assertArrayNear(states.P, b.P, rtol=1e-7)
|
self.assertArrayNear(states.P, b.P, rtol=1e-7)
|
||||||
self.assertArrayNear(states.X, b.X, rtol=1e-7)
|
self.assertArrayNear(states.X, b.X, rtol=1e-7)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif("h5py" not in ct.hdf_support(), reason="h5py is not installed")
|
|
||||||
def test_import_no_norm_water_h5py(self):
|
|
||||||
self.run_import_no_norm_water(legacy=True)
|
|
||||||
|
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
||||||
def test_import_no_norm_water(self):
|
def test_import_no_norm_water(self):
|
||||||
self.run_import_no_norm_water()
|
|
||||||
|
|
||||||
def run_import_no_norm_water(self, legacy=False):
|
|
||||||
# recreate states used to create legacy HDF file
|
# recreate states used to create legacy HDF file
|
||||||
w = ct.Water()
|
w = ct.Water()
|
||||||
w.TQ = 300, 0.5
|
w.TQ = 300, 0.5
|
||||||
@ -878,28 +756,11 @@ class TestLegacyHDF(utilities.CanteraTest):
|
|||||||
w_new = ct.Water()
|
w_new = ct.Water()
|
||||||
infile = self.test_data_path / "solutionarray_water_legacy.h5"
|
infile = self.test_data_path / "solutionarray_water_legacy.h5"
|
||||||
c = ct.SolutionArray(w_new)
|
c = ct.SolutionArray(w_new)
|
||||||
if legacy:
|
c.restore(infile, "group0")
|
||||||
c.read_hdf(infile, normalize=False)
|
|
||||||
else:
|
|
||||||
c.restore(infile, "group0")
|
|
||||||
self.assertArrayNear(states.T, c.T, rtol=1e-7)
|
self.assertArrayNear(states.T, c.T, rtol=1e-7)
|
||||||
self.assertArrayNear(states.P, c.P, rtol=1e-7)
|
self.assertArrayNear(states.P, c.P, rtol=1e-7)
|
||||||
self.assertArrayNear(states.Q, c.Q, rtol=1e-7)
|
self.assertArrayNear(states.Q, c.Q, rtol=1e-7)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif(ct.hdf_support() != {"native", "h5py"},
|
|
||||||
reason="Both HDF support modes needed")
|
|
||||||
def test_new_hdf_h5py_exception(self):
|
|
||||||
outfile = self.test_work_path / f"solutionarray_new.h5"
|
|
||||||
outfile.unlink(missing_ok=True)
|
|
||||||
|
|
||||||
states = ct.SolutionArray(self.gas, 3, extra={'spam': [[1, 2], [3, 4], [5, 6]]})
|
|
||||||
states.save(outfile, "arr")
|
|
||||||
|
|
||||||
b = ct.SolutionArray(self.gas, extra={'spam'})
|
|
||||||
with pytest.raises(IOError, match="Cantera 3.0 HDF format"):
|
|
||||||
b.read_hdf(outfile, "arr") # h5py file should not read new format
|
|
||||||
|
|
||||||
|
|
||||||
class TestRestoreIdealGas(utilities.CanteraTest):
|
class TestRestoreIdealGas(utilities.CanteraTest):
|
||||||
""" Test restoring of the IdealGas class """
|
""" Test restoring of the IdealGas class """
|
||||||
|
@ -84,8 +84,6 @@ class TestOnedim(utilities.CanteraTest):
|
|||||||
ct.ReactingSurface1D(gas, foo="bar")
|
ct.ReactingSurface1D(gas, foo="bar")
|
||||||
interface = ct.Solution("diamond.yaml", "diamond_100")
|
interface = ct.Solution("diamond.yaml", "diamond_100")
|
||||||
surf = ct.ReactingSurface1D(interface)
|
surf = ct.ReactingSurface1D(interface)
|
||||||
with pytest.warns(DeprecationWarning, match="Method to be removed"):
|
|
||||||
surf.set_kinetics(interface)
|
|
||||||
|
|
||||||
def test_invalid_property(self):
|
def test_invalid_property(self):
|
||||||
gas1 = ct.Solution("h2o2.yaml")
|
gas1 = ct.Solution("h2o2.yaml")
|
||||||
@ -293,8 +291,6 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
flow = self.sim.to_array(normalize=True)
|
flow = self.sim.to_array(normalize=True)
|
||||||
self.assertArrayNear(self.sim.grid, flow.grid)
|
self.assertArrayNear(self.sim.grid, flow.grid)
|
||||||
self.assertArrayNear(self.sim.T, flow.T)
|
self.assertArrayNear(self.sim.T, flow.T)
|
||||||
for k in flow.extra:
|
|
||||||
self.assertIn(k, self.sim._other)
|
|
||||||
|
|
||||||
f2 = ct.FreeFlame(self.gas)
|
f2 = ct.FreeFlame(self.gas)
|
||||||
f2.from_array(flow)
|
f2.from_array(flow)
|
||||||
@ -640,8 +636,8 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
# Skipped because they are constant, irrelevant, or otherwise not desired
|
# Skipped because they are constant, irrelevant, or otherwise not desired
|
||||||
"P", "Te", "atomic_weights", "charges", "electric_potential", "max_temp",
|
"P", "Te", "atomic_weights", "charges", "electric_potential", "max_temp",
|
||||||
"min_temp", "molecular_weights", "product_stoich_coeffs",
|
"min_temp", "molecular_weights", "product_stoich_coeffs",
|
||||||
"product_stoich_coeffs3", "product_stoich_coeffs_reversible",
|
"product_stoich_coeffs", "product_stoich_coeffs_reversible",
|
||||||
"reactant_stoich_coeffs", "reactant_stoich_coeffs3", "reference_pressure",
|
"reactant_stoich_coeffs", "reactant_stoich_coeffs", "reference_pressure",
|
||||||
"state", "u", "v",
|
"state", "u", "v",
|
||||||
# Skipped because they are 2D (conversion not implemented)
|
# Skipped because they are 2D (conversion not implemented)
|
||||||
"binary_diff_coeffs", "creation_rates_ddX", "destruction_rates_ddX",
|
"binary_diff_coeffs", "creation_rates_ddX", "destruction_rates_ddX",
|
||||||
@ -732,22 +728,6 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
k1 = gas1.species_index(species)
|
k1 = gas1.species_index(species)
|
||||||
self.assertArrayNear(Y1[k1], Y2[k2])
|
self.assertArrayNear(Y1[k1], Y2[k2])
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
def test_write_csv_legacy(self):
|
|
||||||
filename = self.test_work_path / "onedim-write_csv.csv"
|
|
||||||
# In Python >= 3.8, this can be replaced by the missing_ok argument
|
|
||||||
if filename.is_file():
|
|
||||||
filename.unlink()
|
|
||||||
|
|
||||||
self.create_sim(2e5, 350, 'H2:1.0, O2:2.0', mech="h2o2.yaml")
|
|
||||||
self.sim.write_csv(filename)
|
|
||||||
data = ct.SolutionArray(self.gas)
|
|
||||||
data.read_csv(filename)
|
|
||||||
self.assertArrayNear(data.grid, self.sim.grid)
|
|
||||||
self.assertArrayNear(data.T, self.sim.T)
|
|
||||||
k = self.gas.species_index('H2')
|
|
||||||
self.assertArrayNear(data.X[:, k], self.sim.X[k, :])
|
|
||||||
|
|
||||||
def test_write_csv(self):
|
def test_write_csv(self):
|
||||||
filename = self.test_work_path / "onedim-save.csv"
|
filename = self.test_work_path / "onedim-save.csv"
|
||||||
filename.unlink(missing_ok=True)
|
filename.unlink(missing_ok=True)
|
||||||
@ -761,20 +741,11 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
k = self.gas.species_index('H2')
|
k = self.gas.species_index('H2')
|
||||||
self.assertArrayNear(data.X[:, k], self.sim.X[k, :])
|
self.assertArrayNear(data.X[:, k], self.sim.X[k, :])
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@utilities.unittest.skipIf("h5py" not in ct.hdf_support(), "h5py not installed")
|
|
||||||
def test_restore_legacy_hdf_h5py(self):
|
|
||||||
self.run_restore_legacy_hdf(True)
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
@pytest.mark.usefixtures("allow_deprecated")
|
||||||
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
@pytest.mark.filterwarnings("ignore:.*legacy HDF.*:UserWarning")
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
def test_restore_legacy_hdf(self):
|
def test_restore_legacy_hdf(self):
|
||||||
self.run_restore_legacy_hdf()
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
def run_restore_legacy_hdf(self, legacy=False):
|
|
||||||
# Legacy input file was created using the Cantera 2.6 Python test suite:
|
# Legacy input file was created using the Cantera 2.6 Python test suite:
|
||||||
# - restore_legacy.h5 -> test_onedim.py::TestFreeFlame::test_write_hdf
|
# - restore_legacy.h5 -> test_onedim.py::TestFreeFlame::test_write_hdf
|
||||||
filename = self.test_data_path / f"freeflame_legacy.h5"
|
filename = self.test_data_path / f"freeflame_legacy.h5"
|
||||||
@ -783,10 +754,7 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
desc = 'mixture-averaged simulation'
|
desc = 'mixture-averaged simulation'
|
||||||
|
|
||||||
f = ct.FreeFlame(self.gas)
|
f = ct.FreeFlame(self.gas)
|
||||||
if legacy:
|
meta = f.restore(filename, "group0")
|
||||||
meta = f.read_hdf(filename)
|
|
||||||
else:
|
|
||||||
meta = f.restore(filename, "group0")
|
|
||||||
assert meta['description'] == desc
|
assert meta['description'] == desc
|
||||||
assert meta['cantera_version'] == "2.6.0"
|
assert meta['cantera_version'] == "2.6.0"
|
||||||
|
|
||||||
@ -795,12 +763,10 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
|
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
@pytest.mark.filterwarnings("ignore:.*_FlowBase.settings.*Cantera 3.0.*:DeprecationWarning")
|
|
||||||
def test_save_restore_hdf(self):
|
def test_save_restore_hdf(self):
|
||||||
# save and restore with native format (HighFive only)
|
# save and restore with native format (HighFive only)
|
||||||
self.run_save_restore("h5")
|
self.run_save_restore("h5")
|
||||||
|
|
||||||
@pytest.mark.filterwarnings("ignore:.*_FlowBase.settings.*Cantera 3.0.*:DeprecationWarning")
|
|
||||||
def test_save_restore_yaml(self):
|
def test_save_restore_yaml(self):
|
||||||
self.run_save_restore("yaml")
|
self.run_save_restore("yaml")
|
||||||
|
|
||||||
@ -820,33 +786,6 @@ class TestFreeFlame(utilities.CanteraTest):
|
|||||||
|
|
||||||
self.check_save_restore(f)
|
self.check_save_restore(f)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@pytest.mark.skipif(ct.hdf_support() != {"native", "h5py"},
|
|
||||||
reason="Both HDF support modes needed")
|
|
||||||
def test_deprecated_write_read_hdf(self):
|
|
||||||
filename = self.test_work_path / f"freeflame_deprecated.h5"
|
|
||||||
filename.unlink(missing_ok=True)
|
|
||||||
|
|
||||||
self.run_mix(phi=1.1, T=350, width=2.0, p=2.0, refine=False)
|
|
||||||
desc = 'mixture-averaged simulation'
|
|
||||||
with pytest.warns(DeprecationWarning, match="use 'save' instead"):
|
|
||||||
self.sim.write_hdf(filename, group="group0", description=desc, loglevel=0)
|
|
||||||
|
|
||||||
f = ct.FreeFlame(self.gas)
|
|
||||||
with pytest.raises(IOError, match="use 'restore' instead"):
|
|
||||||
# New HDF format should not be read with 'read_hdf'
|
|
||||||
with pytest.warns(DeprecationWarning, match="use 'restore' instead"):
|
|
||||||
# DeprecationWarning is triggered before IOError is raised
|
|
||||||
f.read_hdf(filename, group="group0")
|
|
||||||
|
|
||||||
meta = f.restore(filename, "group0")
|
|
||||||
assert meta['description'] == desc
|
|
||||||
assert meta['generator'] == "Cantera SolutionArray"
|
|
||||||
assert meta['cantera-version'] == ct.__version__
|
|
||||||
assert meta['git-commit'] == f"'{ct.__git_commit__}'"
|
|
||||||
|
|
||||||
self.check_save_restore(f)
|
|
||||||
|
|
||||||
def check_save_restore(self, f):
|
def check_save_restore(self, f):
|
||||||
# pytest.approx is used as equality for floats cannot be guaranteed for loaded
|
# pytest.approx is used as equality for floats cannot be guaranteed for loaded
|
||||||
# HDF5 files if they were created on a different OS and/or architecture
|
# HDF5 files if they were created on a different OS and/or architecture
|
||||||
@ -1599,16 +1538,6 @@ class TestImpingingJet(utilities.CanteraTest):
|
|||||||
def test_reacting_surface_case3(self):
|
def test_reacting_surface_case3(self):
|
||||||
self.run_reacting_surface(xch4=0.2, tsurf=800.0, mdot=0.1, width=0.2)
|
self.run_reacting_surface(xch4=0.2, tsurf=800.0, mdot=0.1, width=0.2)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
|
||||||
@utilities.unittest.skipIf("h5py" not in ct.hdf_support(), "h5py not installed")
|
|
||||||
def test_restore_legacy_hdf_h5py(self):
|
|
||||||
filename = self.test_data_path / f"impingingjet_legacy.h5"
|
|
||||||
jet = ct.ImpingingJet(gas=self.gas, surface=self.surf_phase)
|
|
||||||
with pytest.raises(IOError, match="Unable to load surface phase"):
|
|
||||||
# legacy HDF format uses TDX state information, which is incomplete for
|
|
||||||
# surfaces
|
|
||||||
jet.read_hdf(filename)
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("allow_deprecated")
|
@pytest.mark.usefixtures("allow_deprecated")
|
||||||
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
@pytest.mark.skipif("native" not in ct.hdf_support(),
|
||||||
reason="Cantera compiled without HDF support")
|
reason="Cantera compiled without HDF support")
|
||||||
|
Loading…
Reference in New Issue
Block a user