Skip to content

Commit

Permalink
[1D] Address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ischoegl authored and speth committed Mar 29, 2020
1 parent afd6f3c commit 8852375
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 133 deletions.
203 changes: 79 additions & 124 deletions interfaces/cython/cantera/onedim.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,67 +71,86 @@ def get_refine_criteria(self):
"""
return super().get_refine_criteria(self.flame)

def set_initial_guess(self, *args, **kwargs):
def set_initial_guess(self, *args, data=None, key=None, **kwargs):
"""
Set the initial guess for the solution, and load restart data if
provided. Derived classes extend this function to set approximations
for the temperature and composition profiles.
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a `SolutionArray`,
pandas' DataFrame, or previously saved CSV or HDF container files.
Note that restart data do not overwrite boundary conditions.
DataFrame and HDF input require working installations of pandas and
PyTables. These packages can be installed using pip (`pandas` and
`tables`) or conda (`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
"""
self._set_initial_guess(*args, **kwargs)
data = kwargs.get('data')
if data:
# load restart data into SolutionArray
if isinstance(data, SolutionArray):
# already a solution array
arr = data
elif isinstance(data, str):
super().set_initial_guess(*args, data=data, key=key, **kwargs)
if not data:
return

# load restart data into SolutionArray
if isinstance(data, SolutionArray):
# already a solution array
arr = data
elif isinstance(data, str):
if data.endswith('.hdf5') or data.endswith('.h5'):
# data source identifies a HDF file
arr = SolutionArray(self.gas, extra=self._extra)
key = kwargs.get('key')
arr.read_hdf(data, key=key)
else:
# data source is a pandas DataFrame
elif data.endswith('.csv'):
# data source identifies a CSV file
arr = SolutionArray(self.gas, extra=self._extra)
arr.from_pandas(data)
arr.read_csv(data)
else:
raise ValueError(
"'{}' does not identify CSV or HDF file.".format(data)
)
else:
# data source is a pandas DataFrame
arr = SolutionArray(self.gas, extra=self._extra)
arr.from_pandas(data)

# get left and right boundaries
left = self.domains[0]
right = self.domains[2]
# get left and right boundaries
left = self.domains[0]
right = self.domains[2]

if isinstance(left, Inlet1D) and isinstance(right, Inlet1D):
# find stagnation plane
i = np.flatnonzero(self.velocity > 0)[-1]
if isinstance(left, Inlet1D) and isinstance(right, Inlet1D):
# find stagnation plane
i = np.flatnonzero(self.velocity > 0)[-1]

# adjust temperatures
T = arr.T
xi = arr.grid[1:-1]
T[1:-1] += (left.T - T[0]) * (1 - xi) + (right.T - T[-1]) * xi
arr.TP = T, self.P
# adjust temperatures
T = arr.T
xi = arr.grid[1:-1]
T[1:-1] += (left.T - T[0]) * (1 - xi) + (right.T - T[-1]) * xi
arr.TP = T, self.P

# adjust velocities
u = arr.velocity
# adjust velocities
u = arr.velocity

self.gas.TPY = left.T, self.P, left.Y
u[:i] = u[:i] * left.mdot / self.gas.density / u[0]
self.gas.TPY = left.T, self.P, left.Y
u[:i] = u[:i] * left.mdot / self.gas.density / u[0]

self.gas.TPY = right.T, self.P, right.Y
u[i:] = - u[i:] * right.mdot / self.gas.density / u[-1]
self.gas.TPY = right.T, self.P, right.Y
u[i:] = - u[i:] * right.mdot / self.gas.density / u[-1]

arr.velocity = u
arr.velocity = u

elif isinstance(left, Inlet1D):
# adjust temperatures
arr.TP = arr.T + left.T - arr.T[0], self.P
elif isinstance(left, Inlet1D):
# adjust temperatures
arr.TP = arr.T + left.T - arr.T[0], self.P

# adjust velocities
if self.flame.flow_type != "Free Flame":
self.gas.TPY = left.T, self.P, left.Y
u0 = left.mdot/self.gas.density
arr.velocity *= u0 / arr.velocity[0]
# adjust velocities
if self.flame.flow_type != "Free Flame":
self.gas.TPY = left.T, self.P, left.Y
u0 = left.mdot/self.gas.density
arr.velocity *= u0 / arr.velocity[0]

self.from_solution_array(arr, restore_boundaries=False)
else:
return None
self.from_solution_array(arr, restore_boundaries=False)

def set_profile(self, component, locations, values):
"""
Expand Down Expand Up @@ -268,7 +287,8 @@ def V(self):
@property
def spread_rate(self):
"""
Array containing the radial velocity divided by radius [1/s] at each point.
Array containing the tangential velocity gradient [1/s] (e.g. radial
velocity divided by radius) at each point.
"""
return self.profile(self.flame, 'spread_rate')

Expand Down Expand Up @@ -663,7 +683,7 @@ def settings(self):

# add values deviating from mode
ix = np.logical_not(np.isclose(tol, values[ix]))
out.update({'{}_{}'.format(tname, c)
out.update({'{}_{}'.format(tname, c): t
for c, t in zip(comp[ix], tol[ix])})

return out
Expand All @@ -677,7 +697,7 @@ def settings(self, s):
'max_time_step_count', 'max_grid_points'}
attr = attr & set(s.keys())
for key in attr:
self.__setattr__(key, s[key])
setattr(self, key, s[key])

# boundary emissivities
if 'emissivity_left' in s or 'emissivity_right' in s:
Expand Down Expand Up @@ -832,23 +852,13 @@ def set_initial_guess(self, locs=[0.0, 0.3, 0.5, 1.0], data=None, key=None):
Set the initial guess for the solution. By default, the adiabatic flame
temperature and equilibrium composition are computed for the inlet gas
composition. Alternatively, a previously calculated result can be
supplied as an initial guess.
supplied as an initial guess via 'data' and 'key' inputs (see
`FlameBase.set_initial_guess`).
:param locs:
A list of four locations to define the temperature and mass fraction
profiles. Profiles rise linearly between the second and third
location. Locations are given as a fraction of the entire domain
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a SolutionArray,
pandas' DataFrame, or a saved HDF container file. Note that restart
data do not overwrite boundary conditions. DataFrame and HDF input
require working installations of pandas and PyTables. These packages
can be installed using pip (`pandas` and `tables`) or conda
(`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
"""
super().set_initial_guess(data=data, key=key)
if data:
Expand Down Expand Up @@ -1074,19 +1084,8 @@ def set_initial_guess(self, data=None, key=None):
gas composition. The temperature profile rises linearly in the first
20% of the flame to Tad, then is flat. The mass fraction profiles are
set similarly. Alternatively, a previously calculated result can be
supplied as an initial guess.
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a SolutionArray,
pandas' DataFrame, or a saved HDF container file. Note that restart
data do not overwrite boundary conditions. DataFrame and HDF input
require working installations of pandas and PyTables. These packages
can be installed using pip (`pandas` and `tables`) or conda
(`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
supplied as an initial guess via 'data' and 'key' inputs (see
`FlameBase.set_initial_guess`).
"""
super().set_initial_guess(data=data, key=key)
if data:
Expand Down Expand Up @@ -1222,21 +1221,10 @@ def __init__(self, gas, grid=None, width=None):

def set_initial_guess(self, data=None, key=None):
"""
Set the initial guess for the solution. By default, the initial guess is
generated by assuming infinitely-fast chemistry. Alternatively, a
previously calculated result can be supplied as an initial guess.
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a SolutionArray,
pandas' DataFrame, or a saved HDF container file. Note that restart
data do not overwrite boundary conditions. DataFrame and HDF input
require working installations of pandas and PyTables. These packages
can be installed using pip (`pandas` and `tables`) or conda
(`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
Set the initial guess for the solution. By default, the initial guess
is generated by assuming infinitely-fast chemistry. Alternatively, a
previously calculated result can be supplied as an initial guess via
'data' and 'key' inputs (see `FlameBase.set_initial_guess`).
"""
super().set_initial_guess(data=data, key=key)
if data:
Expand Down Expand Up @@ -1528,19 +1516,8 @@ def set_initial_guess(self, products='inlet', data=None, key=None):
the equilibrium composition at the adiabatic flame temperature will be
used to form the initial guess. Otherwise the inlet composition will
be used. Alternatively, a previously calculated result can be supplied
as an initial guess.
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a SolutionArray,
pandas' DataFrame, or a saved HDF container file. Note that restart
data do not overwrite boundary conditions. DataFrame and HDF input
require working installations of pandas and PyTables. These packages
can be installed using pip (`pandas` and `tables`) or conda
(`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
as an initial guess via 'data' and 'key' inputs (see
`FlameBase.set_initial_guess`).
"""
super().set_initial_guess(data=data, key=key, products=products)
if data:
Expand Down Expand Up @@ -1619,19 +1596,8 @@ def set_initial_guess(self, equilibrate=True, data=None, key=None):
If `equilibrate` is True, then the products composition and temperature
will be set to the equilibrium state of the reactants mixture.
Alternatively, a previously calculated result can be supplied as an
initial guess.
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a SolutionArray,
pandas' DataFrame, or a saved HDF container file. Note that restart
data do not overwrite boundary conditions. DataFrame and HDF input
require working installations of pandas and PyTables. These packages
can be installed using pip (`pandas` and `tables`) or conda
(`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
initial guess via 'data' and 'key' inputs (see
`FlameBase.set_initial_guess`).
"""
super().set_initial_guess(data=data, key=key, equilibrate=equilibrate)
if data:
Expand Down Expand Up @@ -1725,19 +1691,8 @@ def set_initial_guess(self, data=None, key=None):
"""
Set the initial guess for the solution based on an equiibrium solution.
Alternatively, a previously calculated result can be supplied as an
initial guess.
:param data:
Restart data, which are typically based on an earlier simulation
result. Restart data may be specified using a SolutionArray,
pandas' DataFrame, or a saved HDF container file. Note that restart
data do not overwrite boundary conditions. DataFrame and HDF input
require working installations of pandas and PyTables. These packages
can be installed using pip (`pandas` and `tables`) or conda
(`pandas` and `pytables`).
:param key:
Group identifier within a HDF container file (only used in
combination with HDF restart data).
initial guess via 'data' and 'key' inputs (see
`FlameBase.set_initial_guess`).
"""
super().set_initial_guess(data=data, key=key)

Expand Down
12 changes: 6 additions & 6 deletions interfaces/cython/cantera/onedim.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,9 @@ cdef class _FlowBase(Domain1D):
To be deprecated with version 2.5, and removed thereafter.
Replaced by property `boundary_emissivities`.
"""
warnings.warn("To be removed after Cantera 2.5. "
"Replaced by property 'boundary_emissivities'",
DeprecationWarning)
warnings.warn("Method 'set_boundary_emissivities' to be removed after "
"Cantera 2.5. Replaced by property "
"'boundary_emissivities'", DeprecationWarning)
self.boundary_emissivities = e_left, e_right

property boundary_emissivities:
Expand Down Expand Up @@ -868,7 +868,7 @@ cdef class Sim1D:
def __set__(self, nmax):
self.sim.setMaxTimeStepCount(nmax)

def _set_initial_guess(self, *args, **kwargs):
def set_initial_guess(self, *args, **kwargs):
"""
Store arguments for initial guess and prepare storage for solution.
"""
Expand Down Expand Up @@ -1173,8 +1173,8 @@ cdef class Sim1D:
To be deprecated with version 2.5, and removed thereafter.
Replaced by property `fixed_temperature`.
"""
warnings.warn("To be removed after Cantera 2.5. "
"Replaced by property 'fixed_temperature'",
warnings.warn("Method 'set_fixed_temperature' to be removed after "
"Cantera 2.5. Replaced by property 'fixed_temperature'",
DeprecationWarning)
self.fixed_temperature = T

Expand Down
1 change: 0 additions & 1 deletion interfaces/cython/cantera/test/test_onedim.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ def solve_multi(self):
self.assertEqual(self.sim.transport_model, 'Multi')

def test_flow_type(self):
# Solve with the energy equation disabled
Tin = 300
p = ct.one_atm
reactants = 'H2:0.65, O2:0.5, AR:2'
Expand Down
5 changes: 3 additions & 2 deletions src/oneD/Sim1D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "cantera/numerics/funcs.h"
#include "cantera/base/xml.h"
#include "cantera/numerics/Func1.h"
#include <limits>

using namespace std;

Expand Down Expand Up @@ -513,7 +514,7 @@ int Sim1D::setFixedTemperature(double t)

double Sim1D::fixedTemperature()
{
double t_fixed = -1.;
double t_fixed = std::numeric_limits<double>::quiet_NaN();
for (size_t n = 0; n < nDomains(); n++) {
StFlow* d = dynamic_cast<StFlow*>(&domain(n));
if (d && d->domainType() == cFreeFlow && d->m_tfixed > 0) {
Expand All @@ -526,7 +527,7 @@ double Sim1D::fixedTemperature()

double Sim1D::fixedTemperatureLocation()
{
double z_fixed = -1.;
double z_fixed = std::numeric_limits<double>::quiet_NaN();
for (size_t n = 0; n < nDomains(); n++) {
StFlow* d = dynamic_cast<StFlow*>(&domain(n));
if (d && d->domainType() == cFreeFlow && d->m_tfixed > 0) {
Expand Down

0 comments on commit 8852375

Please sign in to comment.