Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SolutionArray/HDF interface for 1D FlameBase #805

Merged
merged 29 commits into from
Mar 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0d63dd1
[1D] Return FlameBase solution vector as SolutionArray
ischoegl Feb 10, 2020
a2e590e
[1D] Restore FlameBase solution vector from SolutionArray
ischoegl Feb 11, 2020
f34e060
[Thermo] Fix restoration of extra columns in SolutionArray import
ischoegl Feb 12, 2020
16b937d
[1D] Implement pandas/HDF input/output for FlameBase objects
ischoegl Feb 11, 2020
0c6c675
[1D] Differentiate SolutionArray IO for FlameBase-derived classes
ischoegl Feb 12, 2020
8872b39
[1D] Add unit tests for SolutionArray interface
ischoegl Feb 12, 2020
a6e0261
[1D] Implement restart for FreeFlame
ischoegl Feb 13, 2020
bd3d7eb
[1D] Improve docstrings and minor edits
ischoegl Feb 24, 2020
d2e0a7f
[1D] Restore boundaries from SolutionArray
ischoegl Feb 26, 2020
6ab1ee3
[1D] Enable mass fraction export to pandas/HDF
ischoegl Feb 26, 2020
909813b
[1D] Enable saving of simulation settings to HDF
ischoegl Feb 26, 2020
0443d26
[1D] Add missing getters for radiation-enabled simulations
ischoegl Feb 26, 2020
a605fa8
[1D] Enable output of fixed temperature settings for FreeFlame
ischoegl Feb 26, 2020
efa524c
[1D] Add time stamp to HDF output
ischoegl Feb 26, 2020
443aa18
[1D] Deprecate component name 'u' in favor of 'velocity'
ischoegl Feb 26, 2020
005d9eb
[1D] Add unit test for simulation settings output
ischoegl Feb 26, 2020
6190167
[1D] Deprecate component name 'V' in favor of 'vGradient'
ischoegl Feb 26, 2020
139cd0a
[1D] Improve test coverage and minor fixes
ischoegl Feb 27, 2020
e586a69
[1D] Implement setter for simulation settings
ischoegl Feb 27, 2020
80f7a60
[1D] Restore simulation settings from HDF
ischoegl Feb 28, 2020
08f9802
[Examples] Add optional HDF output to adiabatic_flame.py
ischoegl Feb 28, 2020
b89886e
[1D] Address review comments for FlameBase SolutionArray interface
ischoegl Mar 24, 2020
69bc01e
[1D] Clarify V replacement as spread_rate
ischoegl Mar 24, 2020
ca11cbf
[1D] Make flow type accessible from Python
ischoegl Mar 25, 2020
490bf8f
[1D] Streamline approach for restarting simulations from existing data
ischoegl Mar 25, 2020
27adf62
[1D] Add unit tests for remaining restart cases
ischoegl Mar 25, 2020
874e151
[Thermo] Fix newline in SolutionArray.write_csv
ischoegl Mar 27, 2020
b567742
[1D] Write CSV output using SolutionArray.write_csv
ischoegl Mar 27, 2020
7b161e9
[1D] Address review comments
ischoegl Mar 29, 2020
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
2 changes: 1 addition & 1 deletion include/cantera/oneD/Domain1D.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class Domain1D
}

//! index of component with name \a name.
size_t componentIndex(const std::string& name) const;
virtual size_t componentIndex(const std::string& name) const;

void setBounds(size_t n, doublereal lower, doublereal upper) {
m_min[n] = lower;
Expand Down
13 changes: 10 additions & 3 deletions include/cantera/oneD/Sim1D.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,22 @@ class Sim1D : public OneDim
int refine(int loglevel=0);

//! Add node for fixed temperature point of freely propagating flame
int setFixedTemperature(doublereal t);
int setFixedTemperature(double t);

//! Return temperature at the point used to fix the flame location
double fixedTemperature();

//! Return location of the point where temperature is fixed
double fixedTemperatureLocation();

/**
* Set grid refinement criteria. If dom >= 0, then the settings
* apply only to the specified domain. If dom < 0, the settings
* are applied to each domain. @see Refiner::setCriteria.
*/
void setRefineCriteria(int dom = -1, doublereal ratio = 10.0,
doublereal slope = 0.8, doublereal curve = 0.8, doublereal prune = -0.1);
void setRefineCriteria(int dom = -1, double ratio = 10.0,
double slope = 0.8, double curve = 0.8,
double prune = -0.1);

/**
* Get the grid refinement criteria. dom must be greater than
Expand Down
22 changes: 20 additions & 2 deletions include/cantera/oneD/StFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,24 @@ class StFlow : public Domain1D
return m_do_radiation;
}

//! Return radiative heat loss at grid point j
double radiativeHeatLoss(size_t j) const {
return m_qdotRadiation[j];
}

//! Set the emissivities for the boundary values
/*!
* Reads the emissivities for the left and right boundary values in the
* radiative term and writes them into the variables, which are used for the
* calculation.
*/
void setBoundaryEmissivities(doublereal e_left, doublereal e_right);
void setBoundaryEmissivities(double e_left, double e_right);

//! Return emissivitiy at left boundary
double leftEmissivity() const { return m_epsilon_left; }

//! Return emissivitiy at right boundary
double rightEmissivity() const { return m_epsilon_right; }

void fixTemperature(size_t j=npos);

Expand All @@ -215,7 +226,14 @@ class StFlow : public Domain1D
//! Change the grid size. Called after grid refinement.
virtual void resize(size_t components, size_t points);

virtual void setFixedPoint(int j0, doublereal t0) {}
/*!
* @deprecated To be removed after Cantera 2.5.
*/
virtual void setFixedPoint(int j0, doublereal t0) {
// this does nothing and does not appear to be overloaded
warn_deprecated("StFlow::setFixedPoint",
"To be removed after Cantera 2.5.");
}
ischoegl marked this conversation as resolved.
Show resolved Hide resolved

//! Set the gas object state to be consistent with the solution at point j.
void setGas(const doublereal* x, size_t j);
Expand Down
6 changes: 6 additions & 0 deletions interfaces/cython/cantera/_cantera.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -750,16 +750,20 @@ cdef extern from "cantera/oneD/StFlow.h":
void setPressure(double)
void enableRadiation(cbool)
cbool radiationEnabled()
double radiativeHeatLoss(size_t)
double pressure()
void setFixedTempProfile(vector[double]&, vector[double]&)
void setBoundaryEmissivities(double, double)
double leftEmissivity()
double rightEmissivity()
void solveEnergyEqn()
void fixTemperature()
cbool doEnergy(size_t)
void enableSoret(cbool) except +translate_exception
cbool withSoret()
void setFreeFlow()
void setAxisymmetricFlow()
string flowType()


cdef extern from "cantera/oneD/IonFlow.h":
Expand Down Expand Up @@ -815,6 +819,8 @@ cdef extern from "cantera/oneD/Sim1D.h":
size_t maxGridPoints(size_t) except +translate_exception
void setGridMin(int, double) except +translate_exception
void setFixedTemperature(double) except +translate_exception
double fixedTemperature()
double fixedTemperatureLocation()
void setInterrupt(CxxFunc1*) except +translate_exception
void setTimeStepCallback(CxxFunc1*)
void setSteadyCallback(CxxFunc1*)
Expand Down
18 changes: 11 additions & 7 deletions interfaces/cython/cantera/composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,12 +731,16 @@ def restore_data(self, data, labels):
if s in valid_species:
state_data[-1][:, i] = data[:, valid_species[s]]

# labels may include calculated properties that must not be restored
calculated = self._scalar + self._n_species + self._n_reactions
exclude = [l for l in labels
if any([v in l for v in calculated])]
extra = {l: list(data[:, i]) for i, l in enumerate(labels)
if l not in exclude}
# labels may include calculated properties that must not be restored:
# compare column labels to names that are reserved for SolutionArray
# attributes (see `SolutionArray.collect_data`), i.e. scalar values,
# arrays with number of species, and arrays with number of reactions.
exclude = [lab for lab in labels
if any([lab in self._scalar,
'_'.join(lab.split('_')[:-1]) in self._n_species,
lab.split(' ')[0] in self._n_reactions])]
ischoegl marked this conversation as resolved.
Show resolved Hide resolved
extra = {lab: list(data[:, i]) for i, lab in enumerate(labels)
if lab not in exclude}
if len(self._extra):
extra_lists = {k: extra[k] for k in self._extra}
else:
Expand Down Expand Up @@ -861,7 +865,7 @@ def write_csv(self, filename, cols=None, *args, **kwargs):
only with 1D `SolutionArray` objects.
"""
data, labels = self.collect_data(cols=cols, *args, **kwargs)
with open(filename, 'w') as outfile:
with open(filename, 'w', newline='') as outfile:
writer = _csv.writer(outfile)
writer.writerow(labels)
for row in data:
Expand Down
22 changes: 18 additions & 4 deletions interfaces/cython/cantera/examples/onedim/adiabatic_flame.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
"""

import cantera as ct
try:
import pandas as pd
ischoegl marked this conversation as resolved.
Show resolved Hide resolved
import tables
except:
pd = None

# Simulation parameters
p = ct.one_atm # pressure [Pa]
Expand All @@ -29,16 +34,25 @@
f.solve(loglevel=loglevel, auto=True)

# Solve with the energy equation enabled
f.save('h2_adiabatic.xml', 'mix', 'solution with mixture-averaged transport')
if pd:
f.write_hdf('h2_adiabatic.h5', key='mix', mode='w')
else:
f.save('h2_adiabatic.xml', 'mix',
'solution with mixture-averaged transport')

f.show_solution()
print('mixture-averaged flamespeed = {0:7f} m/s'.format(f.u[0]))
print('mixture-averaged flamespeed = {0:7f} m/s'.format(f.velocity[0]))

# Solve with multi-component transport properties
f.transport_model = 'Multi'
f.solve(loglevel) # don't use 'auto' on subsequent solves
f.show_solution()
print('multicomponent flamespeed = {0:7f} m/s'.format(f.u[0]))
f.save('h2_adiabatic.xml', 'multi', 'solution with multicomponent transport')
print('multicomponent flamespeed = {0:7f} m/s'.format(f.velocity[0]))
if pd:
f.write_hdf('h2_adiabatic.h5', key='multi')
else:
f.save('h2_adiabatic.xml', 'multi',
'solution with multicomponent transport')

# write the velocity, temperature, density, and mole fractions to a CSV file
f.write_csv('h2_adiabatic.csv', quiet=False)
18 changes: 10 additions & 8 deletions interfaces/cython/cantera/examples/onedim/diffusion_flame_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ def interrupt_extinction(t):
f.fuel_inlet.mdot *= rel_pressure_increase ** exp_mdot_p
f.oxidizer_inlet.mdot *= rel_pressure_increase ** exp_mdot_p
# Update velocities
f.set_profile('u', normalized_grid,
f.u * rel_pressure_increase ** exp_u_p)
f.set_profile('V', normalized_grid,
f.V * rel_pressure_increase ** exp_V_p)
f.set_profile('velocity', normalized_grid,
f.velocity * rel_pressure_increase ** exp_u_p)
f.set_profile('spread_rate', normalized_grid,
f.spread_rate * rel_pressure_increase ** exp_V_p)
# Update pressure curvature
f.set_profile('lambda', normalized_grid,
f.L * rel_pressure_increase ** exp_lam_p)
Expand Down Expand Up @@ -167,8 +167,10 @@ def interrupt_extinction(t):
f.fuel_inlet.mdot *= strain_factor ** exp_mdot_a
f.oxidizer_inlet.mdot *= strain_factor ** exp_mdot_a
# Update velocities
f.set_profile('u', normalized_grid, f.u * strain_factor ** exp_u_a)
f.set_profile('V', normalized_grid, f.V * strain_factor ** exp_V_a)
f.set_profile('velocity', normalized_grid,
f.velocity * strain_factor ** exp_u_a)
f.set_profile('spread_rate', normalized_grid,
f.spread_rate * strain_factor ** exp_V_a)
# Update pressure curvature
f.set_profile('lambda', normalized_grid, f.L * strain_factor ** exp_lam_a)
try:
Expand Down Expand Up @@ -203,7 +205,7 @@ def interrupt_extinction(t):

# Plot the axial velocity profiles (normalized by the fuel inlet velocity)
# for selected pressures
ax2.plot(f.grid / f.grid[-1], f.u / f.u[0],
ax2.plot(f.grid / f.grid[-1], f.velocity / f.velocity[0],
label='{0:05.1f} bar'.format(p))

ax1.legend(loc=0)
Expand Down Expand Up @@ -231,7 +233,7 @@ def interrupt_extinction(t):

# Plot the axial velocity profiles (normalized by the fuel inlet velocity)
# for the strain rate loop (selected)
ax4.plot(f.grid / f.grid[-1], f.u / f.u[0],
ax4.plot(f.grid / f.grid[-1], f.velocity / f.velocity[0],
label=format(a_max, '.2e') + ' 1/s')

ax3.legend(loc=0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
# List of peak temperatures
T_max = [np.max(f.T)]
# List of maximum axial velocity gradients
a_max = [np.max(np.abs(np.gradient(f.u) / np.gradient(f.grid)))]
a_max = [np.max(np.abs(np.gradient(f.velocity) / np.gradient(f.grid)))]

# Simulate counterflow flames at increasing strain rates until the flame is
# extinguished. To achieve a fast simulation, an initial coarse strain rate
Expand All @@ -109,8 +109,10 @@
f.fuel_inlet.mdot *= strain_factor ** exp_mdot_a
f.oxidizer_inlet.mdot *= strain_factor ** exp_mdot_a
# Update velocities
f.set_profile('u', normalized_grid, f.u * strain_factor ** exp_u_a)
f.set_profile('V', normalized_grid, f.V * strain_factor ** exp_V_a)
f.set_profile('velocity', normalized_grid,
f.velocity * strain_factor ** exp_u_a)
f.set_profile('spread_rate', normalized_grid,
f.spread_rate * strain_factor ** exp_V_a)
# Update pressure curvature
f.set_profile('lambda', normalized_grid, f.L * strain_factor ** exp_lam_a)
try:
Expand All @@ -125,7 +127,7 @@
description='Cantera version ' + ct.__version__ +
', reaction mechanism ' + reaction_mechanism)
T_max.append(np.max(f.T))
a_max.append(np.max(np.abs(np.gradient(f.u) / np.gradient(f.grid))))
a_max.append(np.max(np.abs(np.gradient(f.velocity) / np.gradient(f.grid))))
# If the temperature difference is too small and the minimum relative
# strain rate increase is reached, abort
if ((T_max[-2] - T_max[-1] < delta_T_min) &
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
f.set_refine_criteria(ratio=3, slope=0.07, curve=0.14)

f.solve(loglevel=1, auto=True)
print('\nmixture-averaged flamespeed = {:7f} m/s\n'.format(f.u[0]))
print('\nmixture-averaged flamespeed = {:7f} m/s\n'.format(f.velocity[0]))

# Use the adjoint method to calculate sensitivities
sens = f.get_flame_speed_reaction_sensitivities()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

f.save('CH4_adiabatic.xml', 'ion', 'solution with ionized gas transport')
f.show_solution()
print('mixture-averaged flamespeed = {0:7f} m/s'.format(f.u[0]))
print('mixture-averaged flamespeed = {0:7f} m/s'.format(f.velocity[0]))

# write the velocity, temperature, density, and mole fractions to a CSV file
f.write_csv('CH4_adiabatic.csv', quiet=False)
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ def derivative(x, y):

def computeStrainRates(oppFlame):
# Compute the derivative of axial velocity to obtain normal strain rate
strainRates = derivative(oppFlame.grid, oppFlame.u)
strainRates = derivative(oppFlame.grid, oppFlame.velocity)

# Obtain the location of the max. strain rate upstream of the pre-heat zone.
# This is the characteristic strain rate
maxStrLocation = abs(strainRates).argmax()
minVelocityPoint = oppFlame.u[:maxStrLocation].argmin()
minVelocityPoint = oppFlame.velocity[:maxStrLocation].argmin()

# Characteristic Strain Rate = K
strainRatePoint = abs(strainRates[:minVelocityPoint]).argmax()
Expand Down Expand Up @@ -130,15 +130,17 @@ def solveOpposedFlame(oppFlame, massFlux=0.12, loglevel=1,

# Axial Velocity Plot
plt.subplot(1, 2, 1)
plt.plot(oppFlame.grid, oppFlame.u, 'r', lw=2)
plt.plot(oppFlame.grid, oppFlame.velocity, 'r', lw=2)
plt.xlim(oppFlame.grid[0], oppFlame.grid[-1])
plt.xlabel('Distance (m)')
plt.ylabel('Axial Velocity (m/s)')

# Identify the point where the strain rate is calculated
plt.plot(oppFlame.grid[strainRatePoint], oppFlame.u[strainRatePoint], 'gs')
plt.plot(oppFlame.grid[strainRatePoint],
oppFlame.velocity[strainRatePoint], 'gs')
plt.annotate('Strain-Rate point',
xy=(oppFlame.grid[strainRatePoint], oppFlame.u[strainRatePoint]),
xy=(oppFlame.grid[strainRatePoint],
oppFlame.velocity[strainRatePoint]),
xytext=(0.001, 0.1),
arrowprops={'arrowstyle': '->'})

Expand Down
Loading