Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions include/cantera/base/Solution.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! @file Solution.h

// This file is part of Cantera. See License.txt in the top-level directory or
// at https://cantera.org/license.txt for license and copyright information.

#ifndef CT_SOLUTION_H
#define CT_SOLUTION_H

#include "cantera/base/ctexceptions.h"

namespace Cantera
{

class ThermoPhase;
class Kinetics;
class Transport;

//! A container class holding managers for all pieces defining a phase
class Solution : public std::enable_shared_from_this<Solution>
{
private:
Solution();

public:
~Solution() {}
Solution(const Solution&) = delete;
Solution& operator=(const Solution&) = delete;

static shared_ptr<Solution> create() {
return shared_ptr<Solution>( new Solution );
}

//! Return the name of this Solution object
std::string name() const;

//! Set the name of this Solution object
void setName(const std::string& name);

//! Set the ThermoPhase object
void setThermoPhase(shared_ptr<ThermoPhase> thermo);

//! Set the Kinetics object
void setKinetics(shared_ptr<Kinetics> kinetics);

//! Set the Transport object
void setTransport(shared_ptr<Transport> transport);

//! Accessor for the ThermoPhase object
ThermoPhase& thermo() {
return *m_thermo;
}
Comment thread
ischoegl marked this conversation as resolved.

//! Accessor for the Kinetics object
Kinetics& kinetics() {
return *m_kinetics;
}

//! Accessor for the Transport object
Transport& transport() {
return *m_transport;
}

protected:
shared_ptr<ThermoPhase> m_thermo; //! ThermoPhase manager
shared_ptr<Kinetics> m_kinetics; //! Kinetics manager
shared_ptr<Transport> m_transport; //! Transport manager
Comment thread
ischoegl marked this conversation as resolved.
Outdated
};

}
#endif
10 changes: 10 additions & 0 deletions include/cantera/kinetics/Kinetics.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
namespace Cantera
{

class Solution;

/**
* @defgroup chemkinetics Chemical Kinetics
*/
Expand Down Expand Up @@ -814,6 +816,11 @@ class Kinetics
void selectPhase(const doublereal* data, const thermo_t* phase,
doublereal* phase_data);

//! Set root Solution holding all phase information
virtual void setRoot(std::shared_ptr<Solution> root) {
m_root = root;
}

protected:
//! Cache for saved calculations within each Kinetics object.
ValueCache m_cache;
Expand Down Expand Up @@ -935,6 +942,9 @@ class Kinetics

//! @see skipUndeclaredThirdBodies()
bool m_skipUndeclaredThirdBodies;

//! reference to Solution
std::weak_ptr<Solution> m_root;
};

}
Expand Down
10 changes: 10 additions & 0 deletions include/cantera/thermo/Phase.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ namespace Cantera
* support thermodynamic calculations (see \ref thermoprops).
*/

class Solution;

//! Class Phase is the base class for phases of matter, managing the species and
//! elements in a phase, as well as the independent variables of temperature,
//! mass density, species mass/mole fraction, and other generalized forces and
Expand Down Expand Up @@ -758,6 +760,11 @@ class Phase
m_caseSensitiveSpecies = cflag;
}

//! Set root Solution holding all phase information
virtual void setRoot(std::shared_ptr<Solution> root) {
m_root = root;
}

protected:
//! Cached for saved calculations within each ThermoPhase.
/*!
Expand Down Expand Up @@ -870,6 +877,9 @@ class Phase

//! Entropy at 298.15 K and 1 bar of stable state pure elements (J kmol-1)
vector_fp m_entropy298;

//! reference to Solution
std::weak_ptr<Solution> m_root;
};

}
Expand Down
10 changes: 10 additions & 0 deletions include/cantera/transport/TransportBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ const VelocityBasis VB_SPECIES_2 = 2;
const VelocityBasis VB_SPECIES_3 = 3;
//@}

class Solution;

//! Base class for transport property managers.
/*!
* All classes that compute transport properties for a single phase derive from
Expand Down Expand Up @@ -654,6 +656,11 @@ class Transport
*/
virtual void setThermo(thermo_t& thermo);

//! Set root Solution holding all phase information
virtual void setRoot(std::shared_ptr<Solution> root) {
m_root = root;
}

protected:
//! Enable the transport object for use.
/*!
Expand All @@ -680,6 +687,9 @@ class Transport
//! Velocity basis from which diffusion velocities are computed.
//! Defaults to the mass averaged basis = -2
int m_velocityBasis;

//! reference to Solution
std::weak_ptr<Solution> m_root;
};

}
Expand Down
19 changes: 15 additions & 4 deletions interfaces/cython/cantera/_cantera.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,26 @@ cdef extern from "cantera/thermo/Species.h" namespace "Cantera":
cdef shared_ptr[CxxSpecies] CxxNewSpecies "newSpecies" (CxxAnyMap&) except +translate_exception
cdef vector[shared_ptr[CxxSpecies]] CxxGetSpecies "getSpecies" (CxxAnyValue&) except +translate_exception


cdef extern from "cantera/base/Solution.h" namespace "Cantera":
cdef cppclass CxxSolution "Cantera::Solution":
CxxSolution()
string name()
void setName(string)
void setThermoPhase(shared_ptr[CxxThermoPhase])
void setKinetics(shared_ptr[CxxKinetics])
void setTransport(shared_ptr[CxxTransport])

cdef shared_ptr[CxxSolution] CxxNewSolution "Cantera::Solution::create" ()


cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera":
cdef cppclass CxxThermoPhase "Cantera::ThermoPhase":
CxxThermoPhase()

# miscellaneous
string type()
string report(cbool, double) except +translate_exception
string name()
void setName(string)
string id()
void setID(string)
double minTemp() except +translate_exception
double maxTemp() except +translate_exception
double refPressure() except +translate_exception
Expand Down Expand Up @@ -928,6 +937,8 @@ cdef class GasTransportData:
cdef _assign(self, shared_ptr[CxxTransportData] other)

cdef class _SolutionBase:
cdef shared_ptr[CxxSolution] _base
cdef CxxSolution* base
cdef shared_ptr[CxxThermoPhase] _thermo
cdef CxxThermoPhase* thermo
cdef shared_ptr[CxxKinetics] _kinetics
Expand Down
93 changes: 79 additions & 14 deletions interfaces/cython/cantera/base.pyx
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
# This file is part of Cantera. See License.txt in the top-level directory or
# at https://cantera.org/license.txt for license and copyright information.

from collections import defaultdict as _defaultdict

cdef class _SolutionBase:
def __cinit__(self, infile='', phaseid='', phases=(), origin=None,
def __cinit__(self, infile='', name='', adjacent=(), origin=None,
source=None, yaml=None, thermo=None, species=(),
kinetics=None, reactions=(), **kwargs):

if 'phaseid' in kwargs:
if name is not '':
raise AttributeError('duplicate specification of phase name')

warnings.warn("Keyword 'name' replaces 'phaseid'",
FutureWarning)
name = kwargs['phaseid']

if 'phases' in kwargs:
if len(adjacent)>0:
raise AttributeError(
'duplicate specification of adjacent phases')

warnings.warn("Keyword 'adjacent' replaces 'phases'",
FutureWarning)
adjacent = kwargs['phases']

# Shallow copy of an existing Solution (for slicing support)
cdef _SolutionBase other
if origin is not None:
other = <_SolutionBase?>origin

self.base = other.base
self.thermo = other.thermo
self.kinetics = other.kinetics
self.transport = other.transport
self._base = other._base
self._thermo = other._thermo
self._kinetics = other._kinetics
self._transport = other._transport
Expand All @@ -21,25 +43,67 @@ cdef class _SolutionBase:
self._selected_species = other._selected_species.copy()
return

# Assign base and set managers to NULL
self._base = CxxNewSolution()
self.base = self._base.get()
self.thermo = NULL
self.kinetics = NULL
self.transport = NULL

# Parse inputs
if infile.endswith('.yml') or infile.endswith('.yaml') or yaml:
self._init_yaml(infile, phaseid, phases, yaml)
self._init_yaml(infile, name, adjacent, yaml)
elif infile or source:
self._init_cti_xml(infile, phaseid, phases, source)
self._init_cti_xml(infile, name, adjacent, source)
elif thermo and species:
self._init_parts(thermo, species, kinetics, phases, reactions)
self._init_parts(thermo, species, kinetics, adjacent, reactions)
else:
raise ValueError("Arguments are insufficient to define a phase")

# Initialization of transport is deferred to Transport.__init__
self.transport = NULL
self.base.setThermoPhase(self._thermo)
self.base.setKinetics(self._kinetics)

self._selected_species = np.ndarray(0, dtype=np.integer)

def __init__(self, *args, **kwargs):
if isinstance(self, Transport):
assert self.transport is not NULL

def _init_yaml(self, infile, phaseid, phases, source):
phase_name = pystr(self.base.name())
name = kwargs.get('name')
if name is not None:
self.name = name
else:
self.name = phase_name
Comment thread
ischoegl marked this conversation as resolved.
Outdated

property name:
"""
The name assigned to this object. The default value corresponds
to the CTI/XML/YAML input file phase entry.
"""
def __get__(self):
return pystr(self.base.name())

def __set__(self, name):
self.base.setName(stringify(name))

property composite:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I suggest something along the lines of composite_type or composite_model for this property?

Copy link
Copy Markdown
Member Author

@ischoegl ischoegl Oct 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a tuple of types/models, so I'd prefer to leave it as is (an alternate would be composite_composition, which sounds redundant).

To clarify, composite_type (or composite_model) to me would indicate Solution, Interface, etc. (e.g. a duplicate of type(gas), with gas being a composite object). I wanted to differentiate (and used the name of the declaring module as a guide). I'm open to alternatives though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I see your point on that being a bit misleading. Just composite feels somehow incomplete to me, but I don't have a better suggestion, so we can leave this as is for now.

"""
Returns tuple of thermo/kinetics/transport models associated with
this SolutionBase object.
"""
Comment thread
ischoegl marked this conversation as resolved.
def __get__(self):
thermo = None if self.thermo == NULL \
else pystr(self.thermo.type())
kinetics = None if self.kinetics == NULL \
else pystr(self.kinetics.kineticsType())
transport = None if self.transport == NULL \
else pystr(self.transport.transportType())

return thermo, kinetics, transport

def _init_yaml(self, infile, name, adjacent, source):
"""
Instantiate a set of new Cantera C++ objects from a YAML
phase definition
Expand All @@ -51,7 +115,7 @@ cdef class _SolutionBase:
root = AnyMapFromYamlString(stringify(source))

phaseNode = root[stringify("phases")].getMapWhere(stringify("name"),
stringify(phaseid))
stringify(name))

# Thermo
if isinstance(self, ThermoPhase):
Expand All @@ -66,15 +130,15 @@ cdef class _SolutionBase:

if isinstance(self, Kinetics):
v.push_back(self.thermo)
for phase in phases:
for phase in adjacent:
# adjacent bulk phases for a surface phase
v.push_back(phase.thermo)
self._kinetics = newKinetics(v, phaseNode, root)
self.kinetics = self._kinetics.get()
else:
self.kinetics = NULL

def _init_cti_xml(self, infile, phaseid, phases, source):
def _init_cti_xml(self, infile, name, adjacent, source):
"""
Instantiate a set of new Cantera C++ objects from a CTI or XML
phase definition
Expand All @@ -86,8 +150,8 @@ cdef class _SolutionBase:

# Get XML data
cdef XML_Node* phaseNode
if phaseid:
phaseNode = rootNode.findID(stringify(phaseid))
if name:
phaseNode = rootNode.findID(stringify(name))
else:
phaseNode = rootNode.findByName(stringify('phase'))
if phaseNode is NULL:
Expand All @@ -106,15 +170,15 @@ cdef class _SolutionBase:

if isinstance(self, Kinetics):
v.push_back(self.thermo)
for phase in phases:
for phase in adjacent:
# adjacent bulk phases for a surface phase
v.push_back(phase.thermo)
self.kinetics = newKineticsMgr(deref(phaseNode), v)
self._kinetics.reset(self.kinetics)
else:
self.kinetics = NULL

def _init_parts(self, thermo, species, kinetics, phases, reactions):
def _init_parts(self, thermo, species, kinetics, adjacent, reactions):
"""
Instantiate a set of new Cantera C++ objects based on a string defining
the model type and a list of Species objects.
Expand All @@ -136,7 +200,8 @@ cdef class _SolutionBase:
self.kinetics = CxxNewKinetics(stringify(kinetics))
self._kinetics.reset(self.kinetics)
self.kinetics.addPhase(deref(self.thermo))
for phase in phases:
for phase in adjacent:
# adjacent bulk phases for a surface phase
self.kinetics.addPhase(deref(phase.thermo))
self.kinetics.init()
self.kinetics.skipUndeclaredThirdBodies(True)
Expand Down
Loading