12#include "cantera/oneD/refine.h"
32 for (
size_t n = 0; n <
nDomains(); n++) {
42 "Index out of bounds: {} > {}", iloc,
m_state->size());
43 (*m_state)[iloc] = value;
50 "Index out of bounds: {} > {}", iloc,
m_state->size());
58 "Index out of bounds: {} > {}", iloc,
m_state->size());
62void Sim1D::save(
const string& fname,
const string& name,
const string& desc,
63 bool overwrite,
int compression,
const string& basis,
64 const vector<double>* res)
66 size_t dot = fname.find_last_of(
".");
68 if (extension ==
"csv") {
69 for (
auto dom :
m_dom) {
70 auto arr = dom->toArray();
71 if (dom->size() > 1) {
72 arr->writeEntry(fname, overwrite, basis);
80 "Species basis '{}' not implemented for HDF5 or YAML output.", basis);
82 if (extension ==
"h5" || extension ==
"hdf" || extension ==
"hdf5") {
84 for (
auto dom :
m_dom) {
85 auto arr = dom->toArray();
87 dom->appendResiduals(*arr, span<const double>(
88 res->data() + dom->loc(), dom->size()));
90 arr->writeEntry(fname, name, dom->id(), overwrite, compression);
94 if (extension ==
"yaml" || extension ==
"yml") {
97 if (std::ifstream(fname).good()) {
102 for (
auto dom :
m_dom) {
103 auto arr = dom->toArray();
105 dom->appendResiduals(*arr, span<const double>(
106 res->data() + dom->loc(), dom->size()));
108 arr->writeEntry(data, name, dom->id(), overwrite);
112 std::ofstream out(fname);
113 out << data.toYamlString();
117 throw CanteraError(
"Sim1D::save",
"Unsupported file format '{}'.", extension);
121 const string& desc,
bool overwrite,
int compression)
123 vector<double> res(
m_state->size(), -999);
125 save(fname, name, desc, overwrite, compression,
"", &res);
131AnyMap legacyH5(shared_ptr<SolutionArray> arr,
const AnyMap& header={})
133 auto meta = arr->meta();
136 map<string, string> meta_pairs = {
137 {
"type",
"Domain1D_type"},
139 {
"emissivity-left",
"emissivity_left"},
140 {
"emissivity-right",
"emissivity_right"},
142 for (
const auto& [newName, oldName] : meta_pairs) {
143 if (meta.hasKey(oldName)) {
144 out[newName] = meta[oldName];
148 map<string, string> tol_pairs = {
149 {
"transient-abstol",
"transient_abstol"},
150 {
"steady-abstol",
"steady_abstol"},
151 {
"transient-reltol",
"transient_reltol"},
152 {
"steady-reltol",
"steady_reltol"},
154 for (
const auto& [newName, oldName] : tol_pairs) {
155 if (meta.hasKey(oldName)) {
156 out[
"tolerances"][newName] = meta[oldName];
160 if (meta.hasKey(
"phase")) {
161 out[
"phase"][
"name"] = meta[
"phase"][
"name"];
162 out[
"phase"][
"source"] = meta[
"phase"][
"source"];
165 if (arr->size() <= 1) {
169 map<string, string> header_pairs = {
170 {
"transport-model",
"transport_model"},
171 {
"radiation-enabled",
"radiation_enabled"},
172 {
"energy-enabled",
"energy_enabled"},
173 {
"Soret-enabled",
"soret_enabled"},
175 for (
const auto& [newName, oldName] : header_pairs) {
176 if (header.hasKey(oldName)) {
177 out[newName] = header[oldName];
181 map<string, string> refiner_pairs = {
187 {
"max-points",
"max_grid_points"},
189 for (
const auto& [newName, oldName] : refiner_pairs) {
190 if (header.hasKey(oldName)) {
191 out[
"refine-criteria"][newName] = header[oldName];
195 if (header.hasKey(
"fixed_temperature")) {
196 double temp = header.getDouble(
"fixed_temperature", -1.);
197 auto profile = arr->getComponent(
"T").as<vector<double>>();
199 while (profile[ix] <= temp && ix < arr->size()) {
203 auto grid = arr->getComponent(
"grid").as<vector<double>>();
204 out[
"fixed-point"][
"location"] = grid[ix - 1];
205 out[
"fixed-point"][
"temperature"] = temp;
216 size_t dot = fname.find_last_of(
".");
218 if (extension ==
"xml") {
220 "Restoring from XML is no longer supported.");
223 if (extension ==
"h5" || extension ==
"hdf" || extension ==
"hdf5") {
224 map<string, shared_ptr<SolutionArray>> arrs;
227 for (
auto dom :
m_dom) {
230 arr->readEntry(fname, name, dom->id());
233 "Encountered exception when reading entry '{}' from '{}':\n{}",
236 dom->resize(dom->nComponents(), arr->size());
237 if (!header.
hasKey(
"generator")) {
238 arr->meta() = legacyH5(arr, header);
240 arrs[dom->id()] = arr;
244 for (
auto dom :
m_dom) {
246 dom->fromArray(arrs[dom->id()]);
249 "Encountered exception when restoring domain '{}' from HDF:\n{}",
254 }
else if (extension ==
"yaml" || extension ==
"yml") {
256 map<string, shared_ptr<SolutionArray>> arrs;
259 for (
auto dom :
m_dom) {
262 arr->readEntry(root, name, dom->id());
265 "Encountered exception when reading entry '{}' from '{}':\n{}",
268 dom->resize(dom->nComponents(), arr->size());
269 arrs[dom->id()] = arr;
273 for (
auto dom :
m_dom) {
275 dom->fromArray(arrs[dom->id()]);
278 "Encountered exception when restoring domain '{}' from YAML:\n{}",
285 "Unknown file extension '{}'; supported extensions include "
286 "'h5'/'hdf'/'hdf5' and 'yml'/'yaml'.", extension);
298 for (
size_t n = 0; n <
nDomains(); n++) {
299 if (
domain(n).domainType() !=
"empty") {
301 +
" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
311 throw CanteraError(
"Sim1D::restoreTimeSteppingSolution",
312 "No successful time steps taken on this grid.");
321 "No successful steady state solution");
324 for (
size_t n = 0; n <
nDomains(); n++) {
332 for (
size_t n = 0; n <
nDomains(); n++) {
340 for (
size_t n = 0; n <
nDomains(); n++) {
356 while (new_points > 0) {
362 writelog(
"\nTime stepping failed; attempting to refine the grid and retry "
365 int regrid_result =
refine(loglevel);
366 if (regrid_result != 0) {
372 writelog(
"Regrid retry aborted: grid was unchanged.\n");
381 writelog(
"\nNewton steady-state solve succeeded.\n\n");
383 for (
size_t mm = 1; mm <
nDomains(); mm+=2) {
398 new_points =
refine(loglevel);
402 debuglog(
"grid refinement disabled.\n", loglevel);
406 if (new_points < 0) {
410 for (
auto dom :
m_dom) {
411 span<const double> x(
m_state->data() + dom->loc(), dom->size());
412 span<double> r(
m_xnew.data() + dom->loc(), dom->size());
413 span<int> mask(
m_mask.data() + dom->loc(), dom->size());
414 dom->eval(
npos, x, r, mask);
423 vector<double> znew, xnew;
424 vector<size_t> dsize;
429 for (
size_t n = 0; n <
nDomains(); n++) {
434 auto grid = d.
grid();
450 size_t nstart = znew.size();
451 for (
size_t m = 0; m < npnow; m++) {
454 znew.push_back(d.
z(m));
457 for (
size_t i = 0; i < comp; i++) {
458 xnew.push_back(
_value(n, i, m));
466 double zmid = 0.5*(d.
z(m) + d.
z(m+1));
467 znew.push_back(zmid);
472 for (
size_t i = 0; i < comp; i++) {
473 double xmid = 0.5*(
_value(n, i, m) +
_value(n, i, m+1));
474 xnew.push_back(xmid);
480 writelog(
"refine: discarding point at {}\n", d.
z(m));
484 dsize.push_back(znew.size() - nstart);
491 size_t gridstart = 0, gridsize;
492 for (
size_t n = 0; n <
nDomains(); n++) {
496 d.
setupGrid(span<const double>(znew.data() + gridstart, gridsize));
498 gridstart += gridsize;
505 return added || -discarded;
515 std::filesystem::remove(
"debug_sim1d.yaml");
519 int loglevel,
int attempt_counter)
521 string file_header = fmt::format(
"solution_{}_{}", attempt_counter, header_suffix);
523 saveResidual(
"debug_sim1d.yaml", file_header, message,
true);
524 }
else if (loglevel > 6) {
525 save(
"debug_sim1d.yaml", file_header, message,
true);
532 vector<double> znew, xnew;
534 double z1 = 0.0, z2 = 0.0;
535 vector<size_t> dsize;
537 for (
size_t n = 0; n <
nDomains(); n++) {
540 size_t mfixed =
npos;
545 size_t nstart = znew.size();
546 if (d_free && d_free->
isFree()) {
547 for (
size_t m = 0; m < npnow - 1; m++) {
548 bool fixedpt =
false;
552 double thresh = min(1., 1.e-1 * (t2 - t1));
555 if (fabs(t - t1) <= thresh) {
558 }
else if (fabs(t2 - t) <= thresh) {
561 }
else if ((t1 < t) && (t < t2)) {
563 zfixed = (z1 - z2) / (t1 - t2) * (t - t2) + z2;
576 for (
size_t m = 0; m < npnow; m++) {
578 znew.push_back(d.
z(m));
581 for (
size_t i = 0; i < comp; i++) {
582 xnew.push_back(
_value(n, i, m));
586 znew.push_back(zfixed);
588 double interp_factor = (zfixed - z2) / (z1 - z2);
591 for (
size_t i = 0; i < comp; i++) {
592 double xmid = interp_factor*(
594 xnew.push_back(xmid);
598 dsize.push_back(znew.size() - nstart);
604 size_t gridstart = 0;
605 for (
size_t n = 0; n <
nDomains(); n++) {
607 size_t gridsize = dsize[n];
608 d.
setupGrid(span<const double>(znew.data() + gridstart, gridsize));
609 gridstart += gridsize;
622 double t_fixed = std::numeric_limits<double>::quiet_NaN();
623 for (
size_t n = 0; n <
nDomains(); n++) {
635 double z_fixed = std::numeric_limits<double>::quiet_NaN();
636 for (
size_t n = 0; n <
nDomains(); n++) {
648 bool two_point_domain_found =
false;
649 for (
size_t n = 0; n <
nDomains(); n++) {
664 two_point_domain_found =
true;
666 double current_val, next_val;
667 for (
size_t m = 0; m < np-1; m++) {
670 if ((current_val - temperature) * (next_val - temperature) < 0.0) {
674 if (std::abs(current_val - temperature) <
675 std::abs(next_val - temperature)) {
687 if (!two_point_domain_found) {
689 "No domain with two-point control enabled was found.");
692 "No control point with temperature {} was able to be found in the"
693 "flame's temperature range.", temperature);
699 bool two_point_domain_found =
false;
700 for (
size_t n = 0; n <
nDomains(); n++) {
715 two_point_domain_found =
true;
717 double current_val, next_val;
718 for (
size_t m = np-1; m > 0; m--) {
721 if ((current_val - temperature) * (next_val - temperature) < 0.0) {
725 if (std::abs(current_val - temperature) <
726 std::abs(next_val - temperature)) {
738 if (!two_point_domain_found) {
740 "No domain with two-point control enabled was found.");
743 "No control point with temperature {} was able to be found in the"
744 "flame's temperature range.", temperature);
750 double slope,
double curve,
double prune)
755 for (
size_t n = 0; n <
nDomains(); n++) {
767 "Must specify domain to get criteria from");
777 for (
size_t n = 0; n <
nDomains(); n++) {
790 for (
size_t n = 0; n <
nDomains(); n++) {
810 for (
auto& D :
m_dom) {
811 D->forceFullUpdate(
true);
814 for (
auto& D :
m_dom) {
815 D->forceFullUpdate(
false);
818 auto multijac = dynamic_pointer_cast<MultiJac>(
m_jac);
820 throw CanteraError(
"Sim1D::solveAdjoint",
"Banded (MultiJac) required");
825 for (
size_t i = 0; i <
size(); i++) {
826 size_t j1 = (i > bw) ? i - bw : 0;
827 size_t j2 = (i + bw >=
size()) ?
size() - 1: i + bw;
828 for (
size_t j = j1; j <= j2; j++) {
829 Jt(j,i) = multijac->
value(i,j);
842shared_ptr<Sim1D>
newSim1D(vector<shared_ptr<Domain1D>>& domains)
844 return make_shared<Sim1D>(domains);
A map of string keys to values whose type can vary at runtime.
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
static void clearCachedFile(const string &filename)
Remove the specified file from the input cache if it is present.
static AnyMap fromYamlFile(const string &name, const string &parent_name="")
Create an AnyMap from a YAML file.
A class for banded matrices, involving matrix inversion processes.
void solve(span< const double > b, span< double > x)
Solve the matrix problem Ax = b.
double & value(size_t i, size_t j)
Return a changeable reference to element (i,j).
Base class for exceptions thrown by Cantera classes.
virtual string getMessage() const
Method overridden by derived classes to format the error message.
Base class for one-dimensional domains.
virtual void _getInitialSoln(span< double > x)
Writes some or all initial solution values into the global solution array, beginning at the location ...
virtual void setupGrid(span< const double > z)
Set up initial grid.
size_t nComponents() const
Number of components at each grid point.
size_t size() const
Return the size of the solution vector (the product of m_nv and m_points).
span< double > grid()
Access the array of grid coordinates [m].
size_t nPoints() const
Number of grid points in this domain.
virtual string domainType() const
Domain type flag.
double z(size_t jlocal) const
Get the coordinate [m] of the point with local index jlocal.
Refiner & refiner()
Return a reference to the grid refiner.
virtual void show(span< const double > x)
Print the solution.
size_t index(size_t n, size_t j) const
Returns the index of the solution vector, which corresponds to component n at grid point j.
vector< double > getRefineCriteria()
Get the grid refinement criteria.
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector.
virtual void _finalize(span< const double > x)
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
void setRefineCriteria(double ratio=10.0, double slope=0.8, double curve=0.8, double prune=-0.1)
Set grid refinement criteria.
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
void setLeftControlPointTemperature(double temperature)
Sets the temperature of the left control point.
void setLeftControlPointCoordinate(double z_left)
Sets the coordinate of the left control point.
void setRightControlPointCoordinate(double z_right)
Sets the coordinate of the right control point.
bool twoPointControlEnabled() const
Returns the status of the two-point control.
void setRightControlPointTemperature(double temperature)
Sets the temperature of the right control point.
double m_tfixed
Temperature at the point used to fix the flame location.
double m_zfixed
Location of the point where temperature is fixed.
bool isFree() const
Retrieve flag indicating whether flow is freely propagating.
size_t start(size_t i) const
The index of the start of domain i in the solution vector.
void resize() override
Call to set the size of internal data structures after first defining the system or if the problem si...
size_t nDomains() const
Number of domains.
OneDim()=default
Default constructor.
Domain1D & domain(size_t i) const
Return a reference to domain i.
vector< shared_ptr< Domain1D > > m_dom
All domains comprising the system.
void eval(size_t j, span< const double > x, span< double > r, double rdt=-1.0, int count=1)
Evaluate the multi-domain residual function.
Refine Domain1D grids so that profiles satisfy adaptation tolerances.
bool newPointNeeded(size_t j)
Returns true if a new grid point is needed to the right of grid index j.
size_t maxPoints() const
Returns the maximum number of points allowed in the domain.
int nNewPoints()
Returns the number of new grid points that were needed.
void show()
Displays the results of the grid refinement analysis.
void setMaxPoints(int npmax)
Set the maximum number of points allowed in the domain.
int analyze(size_t n, span< const double > z, span< const double > x)
Determine locations in the grid that need additional grid points and update the internal state of the...
bool keepPoint(size_t j)
Returns true if the grid point at index j should be kept.
void setGridMin(double gridmin)
Set the minimum allowable spacing between adjacent grid points [m].
void getInitialSoln()
Get the initial value of the system state from each domain in the simulation.
void restoreTimeSteppingSolution()
Set the current solution vector to the last successful time-stepping solution.
void resize() override
Call to set the size of internal data structures after first defining the system or if the problem si...
void save(const string &fname, const string &name, const string &desc, bool overwrite=false, int compression=0, const string &basis="", const vector< double > *res=nullptr)
Save current simulation data to a container file or CSV format.
void saveResidual(const string &fname, const string &name, const string &desc, bool overwrite=false, int compression=0)
Save the current solution and its residual vector to a container file.
double fixedTemperatureLocation()
Return location of the point where temperature is fixed.
vector< vector< double > > m_grid_last_ss
the grids for each domain after the last successful steady-state solve (stored before grid refinement...
double _value(size_t dom, size_t comp, size_t localPoint) const
Get one entry in the solution vector.
void finalize()
Calls method _finalize in each domain.
int refine(int loglevel=0)
Refine the grid in all domains.
void show()
Show logging information on current solution for all domains.
double fixedTemperature()
Return temperature at the point used to fix the flame location.
void clearDebugFile() override
Deletes a debug_sim1d.yaml file if it exists.
double _workValue(size_t dom, size_t comp, size_t localPoint) const
Get an entry in the work vector, which may contain either a new system state or the current residual ...
vector< double > m_xlast_ss
the solution vector after the last successful steady-state solve (stored before grid refinement)
void _restore(const string &fname, const string &name)
Retrieve data from a previously saved simulation.
void setMaxGridPoints(int dom, int npoints)
Set the maximum number of grid points in the domain.
int setFixedTemperature(double t)
Add node for fixed temperature point of freely propagating flame.
void solve(int loglevel=0, bool refine_grid=true)
Performs the hybrid Newton steady/time-stepping solution.
void evalSSJacobian()
Evaluate the Jacobian in steady-state mode.
int m_ts_regrid_max
0 disables regrid-on-timestep-failure retries
AnyMap restore(const string &fname, const string &name)
Retrieve data and settings from a previously saved simulation.
Func1 * m_steady_callback
User-supplied function called after a successful steady-state solve.
void solveAdjoint(span< const double > b, span< double > lambda)
Solve the equation .
void restoreSteadySolution()
Set the current solution vector and grid to the last successful steady- state solution.
size_t maxGridPoints(size_t dom)
Get the maximum number of grid points in this domain.
void writeDebugInfo(const string &header_suffix, const string &message, int loglevel, int attempt_counter) override
Write solver debugging information to a YAML file based on the specified log level.
void setRightControlPoint(double temperature)
Set the right control point location using the specified temperature.
vector< double > getRefineCriteria(int dom)
Get the grid refinement criteria.
Sim1D()
Default constructor.
void setGridMin(int dom, double gridmin)
Set the minimum grid spacing in the specified domain(s).
void setRefineCriteria(int dom=-1, double ratio=10.0, double slope=0.8, double curve=0.8, double prune=-0.1)
Set grid refinement criteria.
void _setValue(size_t dom, size_t comp, size_t localPoint, double value)
Set a single value in the solution vector.
void setLeftControlPoint(double temperature)
Set the left control point location using the specified temperature.
static AnyMap readHeader(const string &fname, const string &name)
Read header information from a HDF container file.
static void writeHeader(const string &fname, const string &name, const string &desc, bool overwrite=false)
Write header data to a HDF container file.
static shared_ptr< SolutionArray > create(const shared_ptr< Solution > &sol, int size=0, const AnyMap &meta={})
Instantiate a new SolutionArray reference.
vector< double > m_xnew
Work array used to hold the residual or the new solution.
size_t size() const
Total solution vector length;.
void evalSSJacobian(span< const double > x)
Evaluate the steady-state Jacobian, accessible via linearSolver().
size_t bandwidth() const
Jacobian bandwidth.
shared_ptr< SystemJacobian > m_jac
Jacobian evaluator.
shared_ptr< vector< double > > m_state
Solution vector.
vector< int > m_mask
Transient mask.
void solve(int loglevel=0)
Solve the steady-state problem, taking internal timesteps as necessary until the Newton solver can co...
int m_attempt_counter
Counter used to manage the number of states stored in the debug log file generated by writeDebugInfo(...
vector< double > m_xlast_ts
State vector after the last successful set of time steps.
Error thrown when time stepping cannot proceed and the steady-state solver should be given a chance t...
Header for a file containing miscellaneous numerical functions.
string toLowerCopy(const string &input)
Convert to lower case.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
void debuglog(const string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
void writelog(const string &fmt, const Args &... args)
Write a formatted message to the screen.
double dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
void warn_user(const string &method, const string &msg, const Args &... args)
Print a user warning raised from method as CanteraWarning.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
shared_ptr< Sim1D > newSim1D(vector< shared_ptr< Domain1D > > &domains)
Create a Sim1D object with a list of domains.
@ c_offset_T
temperature [kelvin]
Contains declarations for string manipulation functions within Cantera.