mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
[oneD] Ensure Python API passes Solutions to boundaries
This commit is contained in:
committed by
Ray Speth
parent
3dfb13e8be
commit
760ea59edd
@@ -106,6 +106,10 @@ class Inlet1D : public Boundary1D
|
||||
public:
|
||||
Inlet1D();
|
||||
|
||||
Inlet1D(shared_ptr<Solution> solution) : Inlet1D() {
|
||||
m_solution = solution;
|
||||
}
|
||||
|
||||
//! set spreading rate
|
||||
virtual void setSpreadRate(double V0) {
|
||||
m_V0 = V0;
|
||||
@@ -154,6 +158,10 @@ public:
|
||||
m_type = cEmptyType;
|
||||
}
|
||||
|
||||
Empty1D(shared_ptr<Solution> solution) : Empty1D() {
|
||||
m_solution = solution;
|
||||
}
|
||||
|
||||
virtual void showSolution(const double* x) {}
|
||||
|
||||
virtual void init();
|
||||
@@ -176,6 +184,10 @@ public:
|
||||
m_type = cSymmType;
|
||||
}
|
||||
|
||||
Symm1D(shared_ptr<Solution> solution) : Symm1D() {
|
||||
m_solution = solution;
|
||||
}
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual void eval(size_t jg, double* xg, double* rg,
|
||||
@@ -196,6 +208,10 @@ public:
|
||||
m_type = cOutletType;
|
||||
}
|
||||
|
||||
Outlet1D(shared_ptr<Solution> solution) : Outlet1D() {
|
||||
m_solution = solution;
|
||||
}
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual void eval(size_t jg, double* xg, double* rg,
|
||||
@@ -214,6 +230,10 @@ class OutletRes1D : public Boundary1D
|
||||
public:
|
||||
OutletRes1D();
|
||||
|
||||
OutletRes1D(shared_ptr<Solution> solution) : OutletRes1D() {
|
||||
m_solution = solution;
|
||||
}
|
||||
|
||||
virtual void showSolution(const double* x) {}
|
||||
|
||||
virtual size_t nSpecies() {
|
||||
@@ -251,6 +271,10 @@ public:
|
||||
m_type = cSurfType;
|
||||
}
|
||||
|
||||
Surf1D(shared_ptr<Solution> solution) : Surf1D() {
|
||||
m_solution = solution;
|
||||
}
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual void eval(size_t jg, double* xg, double* rg,
|
||||
|
||||
@@ -48,24 +48,24 @@ cdef extern from "cantera/oneD/Boundary1D.h":
|
||||
double massFraction(size_t)
|
||||
|
||||
cdef cppclass CxxInlet1D "Cantera::Inlet1D":
|
||||
CxxInlet1D()
|
||||
CxxInlet1D(shared_ptr[CxxSolution])
|
||||
double spreadRate()
|
||||
void setSpreadRate(double)
|
||||
|
||||
cdef cppclass CxxOutlet1D "Cantera::Outlet1D":
|
||||
CxxOutlet1D()
|
||||
CxxOutlet1D(shared_ptr[CxxSolution])
|
||||
|
||||
cdef cppclass CxxOutletRes1D "Cantera::OutletRes1D":
|
||||
CxxOutletRes1D()
|
||||
CxxOutletRes1D(shared_ptr[CxxSolution])
|
||||
|
||||
cdef cppclass CxxSymm1D "Cantera::Symm1D":
|
||||
CxxSymm1D()
|
||||
CxxSymm1D(shared_ptr[CxxSolution])
|
||||
|
||||
cdef cppclass CxxSurf1D "Cantera::Surf1D":
|
||||
CxxSurf1D()
|
||||
CxxSurf1D(shared_ptr[CxxSolution])
|
||||
|
||||
cdef cppclass CxxReactingSurf1D "Cantera::ReactingSurf1D":
|
||||
CxxReactingSurf1D()
|
||||
CxxReactingSurf1D() # deprecated in Python API (Cantera 3.0)
|
||||
CxxReactingSurf1D(shared_ptr[CxxSolution]) except +translate_exception
|
||||
void setKineticsMgr(CxxInterfaceKinetics*) except +translate_exception
|
||||
void enableCoverageEquations(cbool) except +translate_exception
|
||||
|
||||
@@ -10,15 +10,16 @@ from ._utils cimport stringify, pystr
|
||||
from ._utils import CanteraError
|
||||
from cython.operator import dereference as deref
|
||||
|
||||
|
||||
# Need a pure-python class to store weakrefs to
|
||||
class _WeakrefProxy:
|
||||
pass
|
||||
|
||||
cdef class Domain1D:
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
def __cinit__(self, _SolutionBase phase not None, *args, **kwargs):
|
||||
self.domain = NULL
|
||||
|
||||
def __init__(self, _SolutionBase phase, *args, name=None, **kwargs):
|
||||
def __init__(self, phase, *args, name=None, **kwargs):
|
||||
self._weakref_proxy = _WeakrefProxy()
|
||||
if self.domain is NULL:
|
||||
raise TypeError("Can't instantiate abstract class Domain1D.")
|
||||
@@ -26,8 +27,6 @@ cdef class Domain1D:
|
||||
if name is not None:
|
||||
self.name = name
|
||||
|
||||
if not isinstance(phase, _SolutionBase):
|
||||
raise TypeError(f"Received phase with invalid type '{type(phase)}'.")
|
||||
self.gas = phase
|
||||
self.gas._references[self._weakref_proxy] = True
|
||||
self.set_default_tolerances()
|
||||
@@ -286,14 +285,11 @@ cdef class Boundary1D(Domain1D):
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.boundary = NULL
|
||||
|
||||
def __init__(self, *args, phase=None, **kwargs):
|
||||
def __init__(self, phase, name=None):
|
||||
if self.boundary is NULL:
|
||||
raise TypeError("Can't instantiate abstract class Boundary1D.")
|
||||
self.domain = <CxxDomain1D*>(self.boundary)
|
||||
if phase is not None:
|
||||
Domain1D.__init__(self, phase, *args, **kwargs)
|
||||
else:
|
||||
Domain1D.__init__(self, *args, **kwargs)
|
||||
Domain1D.__init__(self, phase, name=name)
|
||||
|
||||
property T:
|
||||
""" The temperature [K] at this boundary. """
|
||||
@@ -347,8 +343,8 @@ cdef class Inlet1D(Boundary1D):
|
||||
domain - it must be either the leftmost or rightmost domain in a
|
||||
stack.
|
||||
"""
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.inlet = new CxxInlet1D()
|
||||
def __cinit__(self, _SolutionBase phase, *args, **kwargs):
|
||||
self.inlet = new CxxInlet1D(phase._base)
|
||||
self.boundary = <CxxBoundary1D*>(self.inlet)
|
||||
|
||||
def __dealloc__(self):
|
||||
@@ -369,8 +365,8 @@ cdef class Outlet1D(Boundary1D):
|
||||
A one-dimensional outlet. An outlet imposes a zero-gradient boundary
|
||||
condition on the flow.
|
||||
"""
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.outlet = new CxxOutlet1D()
|
||||
def __cinit__(self, _SolutionBase phase, *args, **kwargs):
|
||||
self.outlet = new CxxOutlet1D(phase._base)
|
||||
self.boundary = <CxxBoundary1D*>(self.outlet)
|
||||
|
||||
def __dealloc__(self):
|
||||
@@ -381,8 +377,8 @@ cdef class OutletReservoir1D(Boundary1D):
|
||||
"""
|
||||
A one-dimensional outlet into a reservoir.
|
||||
"""
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.outlet = new CxxOutletRes1D()
|
||||
def __cinit__(self, _SolutionBase phase, *args, **kwargs):
|
||||
self.outlet = new CxxOutletRes1D(phase._base)
|
||||
self.boundary = <CxxBoundary1D*>(self.outlet)
|
||||
|
||||
def __dealloc__(self):
|
||||
@@ -391,8 +387,8 @@ cdef class OutletReservoir1D(Boundary1D):
|
||||
|
||||
cdef class SymmetryPlane1D(Boundary1D):
|
||||
"""A symmetry plane."""
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.symm = new CxxSymm1D()
|
||||
def __cinit__(self, _SolutionBase phase, *args, **kwargs):
|
||||
self.symm = new CxxSymm1D(phase._base)
|
||||
self.boundary = <CxxBoundary1D*>(self.symm)
|
||||
|
||||
def __dealloc__(self):
|
||||
@@ -401,8 +397,8 @@ cdef class SymmetryPlane1D(Boundary1D):
|
||||
|
||||
cdef class Surface1D(Boundary1D):
|
||||
"""A solid surface."""
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.surf = new CxxSurf1D()
|
||||
def __cinit__(self, _SolutionBase phase, *args, **kwargs):
|
||||
self.surf = new CxxSurf1D(phase._base)
|
||||
self.boundary = <CxxBoundary1D*>(self.surf)
|
||||
|
||||
def __dealloc__(self):
|
||||
@@ -420,39 +416,31 @@ cdef class ReactingSurface1D(Boundary1D):
|
||||
Starting in Cantera 3.0, parameter `phase` should reference surface instead of
|
||||
gas phase.
|
||||
"""
|
||||
def __cinit__(self, *args, phase=None, **kwargs):
|
||||
cdef _SolutionBase sol
|
||||
if isinstance(phase, _SolutionBase) and phase.phase_of_matter != "gas":
|
||||
sol = phase
|
||||
self.surf = new CxxReactingSurf1D(sol._base)
|
||||
def __cinit__(self, _SolutionBase phase, *args, **kwargs):
|
||||
if phase.phase_of_matter != "gas":
|
||||
self.surf = new CxxReactingSurf1D(phase._base)
|
||||
else:
|
||||
# legacy pathway - deprecation is handled in __init__
|
||||
self.surf = new CxxReactingSurf1D()
|
||||
self.boundary = <CxxBoundary1D*>(self.surf)
|
||||
|
||||
def __init__(self, *args, phase=None, **kwargs):
|
||||
def __init__(self, _SolutionBase phase, name=None):
|
||||
self._weakref_proxy = _WeakrefProxy()
|
||||
if phase is None and isinstance(args[0], _SolutionBase):
|
||||
phase = args[0]
|
||||
args = args[1:]
|
||||
cdef _SolutionBase sol
|
||||
if isinstance(phase, _SolutionBase):
|
||||
if phase.phase_of_matter == "gas":
|
||||
warnings.warn("Starting in Cantera 3.0, parameter 'phase' should "
|
||||
"reference surface instead of gas phase.", DeprecationWarning)
|
||||
super().__init__(*args, phase=phase, **kwargs)
|
||||
else:
|
||||
sol = phase
|
||||
gas = None
|
||||
for val in sol._adjacent.values():
|
||||
if val.phase_of_matter == "gas":
|
||||
gas = val
|
||||
break
|
||||
if gas is None:
|
||||
raise CanteraError("ReactingSurface1D needs an adjacent gas phase")
|
||||
super().__init__(*args, phase=gas, **kwargs)
|
||||
if phase.phase_of_matter == "gas":
|
||||
warnings.warn("Starting in Cantera 3.0, parameter 'phase' should "
|
||||
"reference surface instead of gas phase.", DeprecationWarning)
|
||||
super().__init__(phase, name=name)
|
||||
else:
|
||||
super().__init__(*args, phase=phase, **kwargs)
|
||||
sol = phase
|
||||
gas = None
|
||||
for val in sol._adjacent.values():
|
||||
if val.phase_of_matter == "gas":
|
||||
gas = val
|
||||
break
|
||||
if gas is None:
|
||||
raise CanteraError("ReactingSurface1D needs an adjacent gas phase")
|
||||
super().__init__(gas, name=name)
|
||||
|
||||
self.surface = phase
|
||||
self.surface._references[self._weakref_proxy] = True
|
||||
|
||||
|
||||
@@ -612,24 +612,22 @@ ReactingSurf1D::ReactingSurf1D()
|
||||
|
||||
ReactingSurf1D::ReactingSurf1D(shared_ptr<Solution> solution)
|
||||
{
|
||||
if (!std::dynamic_pointer_cast<SurfPhase>(solution->thermo())) {
|
||||
auto phase = std::dynamic_pointer_cast<SurfPhase>(solution->thermo());
|
||||
if (!phase) {
|
||||
throw CanteraError("ReactingSurf1D::ReactingSurf1D",
|
||||
"Detected incompatible ThermoPhase type '{}'", solution->thermo()->type());
|
||||
}
|
||||
if (!std::dynamic_pointer_cast<InterfaceKinetics>(solution->kinetics())) {
|
||||
auto kin = std::dynamic_pointer_cast<InterfaceKinetics>(solution->kinetics());
|
||||
if (!kin) {
|
||||
throw CanteraError("ReactingSurf1D::ReactingSurf1D",
|
||||
"Detected incompatible kinetics type '{}'",
|
||||
solution->kinetics()->kineticsType());
|
||||
}
|
||||
m_solution = solution;
|
||||
m_kin = (InterfaceKinetics*)solution->kinetics().get();
|
||||
m_kin = kin.get();
|
||||
m_sphase = phase.get();
|
||||
|
||||
m_surfindex = m_kin->surfacePhaseIndex();
|
||||
m_sphase = (SurfPhase*)&m_kin->thermo(m_surfindex);
|
||||
if (m_sphase->name() != m_solution->thermo()->name()) {
|
||||
throw CanteraError("ReactingSurf1D::ReactingSurf1D",
|
||||
"Detected inconsistent ThermoPhase objects: mismatch of '{}' and '{}'.",
|
||||
m_sphase->name(), m_solution->thermo()->name());
|
||||
}
|
||||
m_nsp = m_sphase->nSpecies();
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,19 @@ class TestOnedim(utilities.CanteraTest):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
copy.copy(flame)
|
||||
|
||||
def test_exceptions(self):
|
||||
with pytest.raises(TypeError, match="Argument 'phase' has incorrect type"):
|
||||
ct.Inlet1D(None)
|
||||
gas = ct.Solution("h2o2.yaml")
|
||||
with pytest.warns(DeprecationWarning, match="should reference surface"):
|
||||
ct.ReactingSurface1D(gas)
|
||||
with pytest.raises(TypeError, match="unexpected keyword"):
|
||||
ct.ReactingSurface1D(gas, foo="bar")
|
||||
interface = ct.Solution("diamond.yaml", "diamond_100")
|
||||
surf = ct.ReactingSurface1D(interface)
|
||||
with pytest.warns(DeprecationWarning, match="Method to be removed"):
|
||||
surf.set_kinetics(interface)
|
||||
|
||||
def test_invalid_property(self):
|
||||
gas1 = ct.Solution("h2o2.yaml")
|
||||
inlet = ct.Inlet1D(name='something', phase=gas1)
|
||||
|
||||
Reference in New Issue
Block a user