diff --git a/include/cantera/thermo/IdealSolidSolnPhase.h b/include/cantera/thermo/IdealSolidSolnPhase.h index f3c0d966eaf..9f75e8fc78b 100644 --- a/include/cantera/thermo/IdealSolidSolnPhase.h +++ b/include/cantera/thermo/IdealSolidSolnPhase.h @@ -85,6 +85,12 @@ class IdealSolidSolnPhase : public ThermoPhase return "IdealSolidSoln"; } + virtual std::vector defaultState() const; + virtual std::vector fullStates() const; + virtual std::vector partialStates() const; + virtual void saveState(size_t lenstate, doublereal* state) const; + virtual void restoreState(size_t lenstate, const doublereal* state); + //! @name Molar Thermodynamic Properties of the Solution //! @{ diff --git a/include/cantera/thermo/Phase.h b/include/cantera/thermo/Phase.h index 1341d35e3b8..aa5922937a7 100644 --- a/include/cantera/thermo/Phase.h +++ b/include/cantera/thermo/Phase.h @@ -77,9 +77,6 @@ namespace Cantera * complicated assemblies of %Cantera Phases. * * @todo - * - Make the concept of saving state vectors more general, so that it can - * handle other cases where there are additional internal state variables, - * such as the voltage, a potential energy, or a strain field. * - Specify that the input mole, mass, and volume fraction vectors must sum * to one on entry to the set state routines. Non-conforming mole/mass * fraction vectors are not thermodynamically consistent. Moreover, unless diff --git a/interfaces/cython/cantera/thermo.pyx b/interfaces/cython/cantera/thermo.pyx index bed9a5479b1..1438a95d9a9 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -303,6 +303,17 @@ cdef class ThermoPhase(_SolutionBase): states = self.thermo.partialStates() states = [s.decode('utf-8') for s in states] return {frozenset(k): k for k in states} + + def _check_property(self, prop): + """ + Check whether *prop* represents a valid (partial) thermodynamic state + """ + valid = any([prop in self._full_states.values(), + prop in self._partial_states.values()]) + if not valid: + raise AttributeError("Setter/getter '{}' is not defined " + "for phase '{}'".format(prop, self.name)) + return valid property name: """ @@ -1015,8 +1026,10 @@ cdef class ThermoPhase(_SolutionBase): property TD: """Get/Set temperature [K] and density [kg/m^3 or kmol/m^3].""" def __get__(self): + self._check_property('TD') return self.T, self.density def __set__(self, values): + self._check_property('TD') assert len(values) == 2, 'incorrect number of values' T = values[0] if values[0] is not None else self.T D = values[1] if values[1] is not None else self.density @@ -1028,8 +1041,10 @@ cdef class ThermoPhase(_SolutionBase): fractions. """ def __get__(self): + self._check_property('TDX') return self.T, self.density, self.X def __set__(self, values): + self._check_property('TDX') assert len(values) == 3, 'incorrect number of values' T = values[0] if values[0] is not None else self.T D = values[1] if values[1] is not None else self.density @@ -1042,8 +1057,10 @@ cdef class ThermoPhase(_SolutionBase): fractions. """ def __get__(self): + self._check_property('TDY') return self.T, self.density, self.Y def __set__(self, values): + self._check_property('TDY') assert len(values) == 3, 'incorrect number of values' T = values[0] if values[0] is not None else self.T D = values[1] if values[1] is not None else self.density @@ -1088,8 +1105,10 @@ cdef class ThermoPhase(_SolutionBase): [m^3/kg or m^3/kmol]. """ def __get__(self): + self._check_property('UV') return self.u, self.v def __set__(self, values): + self._check_property('UV') assert len(values) == 2, 'incorrect number of values' U = values[0] if values[0] is not None else self.u V = values[1] if values[1] is not None else self.v @@ -1102,8 +1121,10 @@ cdef class ThermoPhase(_SolutionBase): [m^3/kg or m^3/kmol], and mole fractions. """ def __get__(self): + self._check_property('UVX') return self.u, self.v, self.X def __set__(self, values): + self._check_property('UVX') assert len(values) == 3, 'incorrect number of values' U = values[0] if values[0] is not None else self.u V = values[1] if values[1] is not None else self.v @@ -1117,8 +1138,10 @@ cdef class ThermoPhase(_SolutionBase): [m^3/kg or m^3/kmol], and mass fractions. """ def __get__(self): + self._check_property('UVY') return self.u, self.v, self.Y def __set__(self, values): + self._check_property('UVY') assert len(values) == 3, 'incorrect number of values' U = values[0] if values[0] is not None else self.u V = values[1] if values[1] is not None else self.v @@ -1129,8 +1152,10 @@ cdef class ThermoPhase(_SolutionBase): property DP: """Get/Set density [kg/m^3] and pressure [Pa].""" def __get__(self): + self._check_property('DP') return self.density, self.P def __set__(self, values): + self._check_property('DP') assert len(values) == 2, 'incorrect number of values' D = values[0] if values[0] is not None else self.density P = values[1] if values[1] is not None else self.P @@ -1139,8 +1164,10 @@ cdef class ThermoPhase(_SolutionBase): property DPX: """Get/Set density [kg/m^3], pressure [Pa], and mole fractions.""" def __get__(self): + self._check_property('DPX') return self.density, self.P, self.X def __set__(self, values): + self._check_property('DPX') assert len(values) == 3, 'incorrect number of values' D = values[0] if values[0] is not None else self.density P = values[1] if values[1] is not None else self.P @@ -1150,8 +1177,10 @@ cdef class ThermoPhase(_SolutionBase): property DPY: """Get/Set density [kg/m^3], pressure [Pa], and mass fractions.""" def __get__(self): + self._check_property('DPY') return self.density, self.P, self.Y def __set__(self, values): + self._check_property('DPY') assert len(values) == 3, 'incorrect number of values' D = values[0] if values[0] is not None else self.density P = values[1] if values[1] is not None else self.P @@ -1228,8 +1257,10 @@ cdef class ThermoPhase(_SolutionBase): m^3/kmol]. """ def __get__(self): + self._check_property('SV') return self.s, self.v def __set__(self, values): + self._check_property('SV') assert len(values) == 2, 'incorrect number of values' S = values[0] if values[0] is not None else self.s V = values[1] if values[1] is not None else self.v @@ -1242,8 +1273,10 @@ cdef class ThermoPhase(_SolutionBase): m^3/kmol], and mole fractions. """ def __get__(self): + self._check_property('SVX') return self.s, self.v, self.X def __set__(self, values): + self._check_property('SVX') assert len(values) == 3, 'incorrect number of values' S = values[0] if values[0] is not None else self.s V = values[1] if values[1] is not None else self.v @@ -1257,8 +1290,10 @@ cdef class ThermoPhase(_SolutionBase): m^3/kmol], and mass fractions. """ def __get__(self): + self._check_property('SVY') return self.s, self.v, self.Y def __set__(self, values): + self._check_property('SVY') assert len(values) == 3, 'incorrect number of values' S = values[0] if values[0] is not None else self.s V = values[1] if values[1] is not None else self.v diff --git a/src/thermo/IdealSolidSolnPhase.cpp b/src/thermo/IdealSolidSolnPhase.cpp index a9c211947a7..83ff033fdaf 100644 --- a/src/thermo/IdealSolidSolnPhase.cpp +++ b/src/thermo/IdealSolidSolnPhase.cpp @@ -56,6 +56,45 @@ IdealSolidSolnPhase::IdealSolidSolnPhase(XML_Node& root, const std::string& id_, importPhase(root, this); } +vector IdealSolidSolnPhase::defaultState() const +{ + const vector props = {"T", "P", "Y"}; + + return props; +} + +vector IdealSolidSolnPhase::fullStates() const +{ + const vector states = {"TPX", "TPY", "HPX", "HPY", + "SPX", "SPY"}; + return states; +} + +vector IdealSolidSolnPhase::partialStates() const +{ + const vector states = {"TP", "HP", "SP"}; + return states; +} + +void IdealSolidSolnPhase::saveState(size_t lenstate, doublereal* state) const +{ + state[0] = temperature(); + state[1] = pressure(); + getMassFractions(state + 2); +} + +void IdealSolidSolnPhase::restoreState(size_t lenstate, const doublereal* state) +{ + if (lenstate >= nSpecies() + 2) { + setMassFractions_NoNorm(state + 2); + setTemperature(state[0]); + setPressure(state[1]); + } else { + throw ArraySizeError("IdealSolidSolnPhase::restoreState", + lenstate,nSpecies()+2); + } +} + // Molar Thermodynamic Properties of the Solution doublereal IdealSolidSolnPhase::enthalpy_mole() const