diff --git a/interfaces/cython/cantera/composite.py b/interfaces/cython/cantera/composite.py index 9de1f500bb7..83c418ab64d 100644 --- a/interfaces/cython/cantera/composite.py +++ b/interfaces/cython/cantera/composite.py @@ -628,7 +628,7 @@ def __call__(self, *species): return SolutionArray(self._phase[species], states=self._states, extra=self._extra) - def append(self, state=None, normalize=None, **kwargs): + def append(self, state=None, normalize=True, **kwargs): """ Append an element to the array with the specified state. Elements can only be appended in cases where the array of states is one-dimensional. @@ -650,14 +650,9 @@ def append(self, state=None, normalize=None, **kwargs): mystates.append(T=300, P=101325, X={'O2':1.0, 'N2':3.76}) - By default, the mass or mole fractions will be non-normalized - if appending a `state` or numpy array specifying `X` or `Y`. - When appending a state, the mass or mole fractions are always - non-normalized. For states setters, if the non-normalized - form is desired, the ``normalize`` argument can be set to ``True``. - For example:: - - mystates.append(T=300, P=101325, Y=gas.Y - 0.1, normalize=True) + 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``. """ if len(self._shape) != 1: raise IndexError("Can only append to 1D SolutionArray") @@ -690,24 +685,19 @@ def append(self, state=None, normalize=None, **kwargs): raise KeyError( "'{}' does not specify a full thermodynamic state".format(attr) ) - if attr[-1] == "X": - if not normalize and isinstance(value[-1], np.ndarray): + if normalize or attr.endswith("Q"): + setattr(self._phase, attr, value) + else: + if attr.endswith("X"): self._phase.set_unnormalized_mole_fractions(value[-1]) attr = attr[:-1] value = value[:-1] setattr(self._phase, attr, value) - else: - setattr(self._phase, attr, value) - elif attr[-1] == "Y": - if not normalize and isinstance(value[-1], np.ndarray): + elif attr.endswith("X"): self._phase.set_unnormalized_mass_fractions(value[-1]) attr = attr[:-1] value = value[:-1] setattr(self._phase, attr, value) - else: - setattr(self._phase, attr, value) - else: - setattr(self._phase, attr, value) else: try: @@ -717,22 +707,17 @@ def append(self, state=None, normalize=None, **kwargs): "{} is not a valid combination of properties for setting " "the thermodynamic state".format(tuple(kwargs)) ) from None - if attr[-1] == "X": - if not normalize and isinstance(kwargs["X"], np.ndarray): + if normalize or attr.endswith("Q"): + setattr(self._phase, attr, list(kwargs.values())) + else: + if attr.endswith("X"): self._phase.set_unnormalized_mole_fractions(kwargs.pop("X")) attr = attr[:-1] setattr(self._phase, attr, list(kwargs.values())) - else: - setattr(self._phase, attr, list(kwargs.values())) - elif attr[-1] == "Y": - if not normalize and isinstance(kwargs["Y"], np.ndarray): + elif attr.endswith("Y"): self._phase.set_unnormalized_mass_fractions(kwargs.pop("Y")) attr = attr[:-1] setattr(self._phase, attr, list(kwargs.values())) - else: - setattr(self._phase, attr, list(kwargs.values())) - else: - setattr(self._phase, attr, list(kwargs.values())) for name, value in self._extra.items(): new = extra_temp[name] @@ -791,7 +776,7 @@ def equilibrate(self, *args, **kwargs): self._phase.equilibrate(*args, **kwargs) self._states[index][:] = self._phase.state - def restore_data(self, data, normalize=False): + def restore_data(self, data, normalize=True): """ Restores a `SolutionArray` based on *data* specified in an ordered dictionary. Thus, this method allows to restore data exported by @@ -800,6 +785,9 @@ def restore_data(self, data, normalize=False): :param data: Dictionary holding data to be restored, where keys refer to thermodynamic states (e.g. ``T``, ``density``) or extra entries, and values contain corresponding data. + :param normalize: If True, mole or mass fractions are normalized + i.e. they sum up to 1.0. If False, mole or mass fractions + are non-normalized. The receiving `SolutionArray` either has to be empty or should have matching dimensions. Essential state properties and extra entries @@ -808,10 +796,6 @@ def restore_data(self, data, normalize=False): entries already specified, only those will be imported; if *labels* does not contain those entries, an error is raised. - If the data contains mass or mole fractions they will be set - without normalizing their sum to 1.0 by default. If this is - not desired, the ``normalize`` argument can be set to ``True`` - to force the data to sum to 1.0. """ # check arguments @@ -950,19 +934,19 @@ def join(species): self._shape = (rows,) # restore data - if normalize or mode[-1] == "Q": + if normalize or mode.endswith("Q"): for i in self._indices: setattr(self._phase, mode, [st[i, ...] for st in state_data]) self._states[i] = self._phase.state else: for i in self._indices: - if mode[-1] == "X": + if mode.endswith("X"): self._phase.set_unnormalized_mole_fractions( [st[i, ...] for st in state_data][2] ) setattr(self._phase, mode[:2], [st[i, ...] for st in state_data[:2]]) - elif mode[-1] == "Y": + elif mode.endswith("Y"): self._phase.set_unnormalized_mass_fractions( [st[i, ...] for st in state_data][2] ) @@ -1110,7 +1094,7 @@ def read_csv(self, filename, normalize=True): previously exported by `write_csv`. The ``normalize`` argument is passed on to `restore_data` to normalize - mole or mass fractions, if desired. By default, ``normalize`` is ``True``. + mole or mass fractions. By default, ``normalize`` is ``True``. """ if np.lib.NumpyVersion(np.__version__) < "1.14.0": # bytestring needs to be converted for columns containing strings @@ -1156,7 +1140,7 @@ def from_pandas(self, df, normalize=True): installation. The package 'pandas' can be installed using pip or conda. The ``normalize`` argument is passed on to `restore_data` to normalize - mole or mass fractions, if desired. By default, ``normalize`` is ``True``.. + mole or mass fractions. By default, ``normalize`` is ``True``.. """ @@ -1311,14 +1295,15 @@ def read_hdf(self, filename, group=None, subgroup=None, force=False, normalize=T `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 i.e. they sum up to 1.0. If False, mole + or mass fractions are non-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). - The ``normalize`` argument is passed on to `restore_data` to normalize - mole or mass fractions, if desired. By default, ``normalize`` is ``True``. """ if isinstance(_h5py, ImportError): raise _h5py diff --git a/interfaces/cython/cantera/onedim.py b/interfaces/cython/cantera/onedim.py index e2269cdd84d..0da4bf4953f 100644 --- a/interfaces/cython/cantera/onedim.py +++ b/interfaces/cython/cantera/onedim.py @@ -377,7 +377,7 @@ def set_gas_state(self, point): self.gas.set_unnormalized_mass_fractions(Y) self.gas.TP = self.value(self.flame, 'T', point), self.P - def write_csv(self, filename, species='X', quiet=True, normalize=False): + def write_csv(self, filename, species='X', quiet=True, normalize=True): """ Write the velocity, temperature, density, and species profiles to a CSV file. @@ -389,7 +389,7 @@ def write_csv(self, filename, species='X', quiet=True, normalize=False): mole fractions or ``Y`` for mass fractions. :param normalize: Boolean flag to indicate whether the mole/mass fractions should - be normalized (default is ``False``) + be normalized (default is ``True``) """ # save data @@ -399,16 +399,15 @@ def write_csv(self, filename, species='X', quiet=True, normalize=False): if not quiet: print("Solution saved to '{0}'.".format(filename)) - def to_solution_array(self, domain=None, normalize=False): + def to_solution_array(self, domain=None, normalize=True): """ Return the solution vector as a `SolutionArray` object. Derived classes define default values for *other*. - If the data contains mass or mole fractions they will be set - without normalizing their sum to 1.0 by default. If this is - not desired, the ``normalize`` argument can be set to - ``True`` to force the data to sum to 1.0. + 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``. """ if domain is None: domain = self.flame @@ -435,7 +434,7 @@ def to_solution_array(self, domain=None, normalize=False): arr._phase.TP = states[0][i], states[1] arr._states[i] = arr._phase.state else: - arr.TPY = states + arr.TP = states return arr else: return SolutionArray(self.phase(domain), meta=meta) @@ -458,7 +457,7 @@ def from_solution_array(self, arr, domain=None): meta = arr.meta super().restore_data(domain, states, other_cols, meta) - def to_pandas(self, species='X', normalize=False): + def to_pandas(self, species='X', normalize=True): """ Return the solution vector as a `pandas.DataFrame`. @@ -467,7 +466,7 @@ def to_pandas(self, species='X', normalize=False): mole fractions or ``Y`` for mass fractions. :param normalize: Boolean flag to indicate whether the mole/mass fractions should - be normalized (default is ``False``) + be normalized (default is ``True``) This method uses `to_solution_array` and requires a working pandas installation. Use pip or conda to install `pandas` to enable this @@ -501,7 +500,7 @@ def from_pandas(self, df, restore_boundaries=True, settings=None): def write_hdf(self, filename, *args, group=None, species='X', mode='a', description=None, compression=None, compression_opts=None, - quiet=True, normalize=False, **kwargs): + quiet=True, normalize=True, **kwargs): """ Write the solution vector to a HDF container file. @@ -564,7 +563,7 @@ def write_hdf(self, filename, *args, group=None, species='X', mode='a', Suppress message confirming successful file output. :param normalize: Boolean flag to indicate whether the mole/mass fractions should - be normalized (default is ``False``) + be normalized (default is ``True``) Additional arguments (i.e. *args* and *kwargs*) are passed on to `SolutionArray.collect_data`. The method exports data using diff --git a/interfaces/cython/cantera/test/test_composite.py b/interfaces/cython/cantera/test/test_composite.py index 9375dc4613b..8befcc5a212 100644 --- a/interfaces/cython/cantera/test/test_composite.py +++ b/interfaces/cython/cantera/test/test_composite.py @@ -155,9 +155,10 @@ def test_append_no_norm_data(self): self.assertArrayNear(states[0].Y, gas.Y) def test_import_no_norm_data(self): - outfile = pjoin(self.test_work_dir, "solutionarray.h5") - if os.path.exists(outfile): - os.remove(outfile) + outfile = self.test_work_path / "solutionarray.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if outfile.is_file(): + outfile.unlink() gas = ct.Solution("h2o2.yaml") gas.set_unnormalized_mole_fractions(np.full(gas.n_species, 0.3)) @@ -454,9 +455,10 @@ def check(a, b): check(a, b) def test_import_no_norm_water(self): - outfile = pjoin(self.test_work_dir, "solutionarray.h5") - if os.path.exists(outfile): - os.remove(outfile) + outfile = self.test_work_path / "solutionarray.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if outfile.is_file(): + outfile.unlink() w = ct.Water() w.TQ = 300, 0.5