/** * @file Domain1D.cpp */ #include "cantera/oneD/Domain1D.h" #include "cantera/base/ctml.h" #include using namespace std; using namespace ctml; namespace Cantera { void Domain1D:: setTolerances(size_t nr, const doublereal* rtol, size_t na, const doublereal* atol, int ts) { if (nr < m_nv || na < m_nv) throw CanteraError("Domain1D::setTolerances", "wrong array size for solution error tolerances. " "Size should be at least "+int2str(m_nv)); if (ts >= 0) { copy(rtol, rtol + m_nv, m_rtol_ss.begin()); copy(atol, atol + m_nv, m_atol_ss.begin()); } if (ts <= 0) { copy(rtol, rtol + m_nv, m_rtol_ts.begin()); copy(atol, atol + m_nv, m_atol_ts.begin()); } } void Domain1D:: setTolerances(size_t n, doublereal rtol, doublereal atol, int ts) { if (ts >= 0) { m_rtol_ss[n] = rtol; m_atol_ss[n] = atol; } if (ts <= 0) { m_rtol_ts[n] = rtol; m_atol_ts[n] = atol; } } void Domain1D:: setTolerances(doublereal rtol, doublereal atol,int ts) { for (size_t n = 0; n < m_nv; n++) { if (ts >= 0) { m_rtol_ss[n] = rtol; m_atol_ss[n] = atol; } if (ts <= 0) { m_rtol_ts[n] = rtol; m_atol_ts[n] = atol; } } } void Domain1D:: setTolerancesTS(doublereal rtol, doublereal atol) { for (size_t n = 0; n < m_nv; n++) { m_rtol_ts[n] = rtol; m_atol_ts[n] = atol; } } void Domain1D:: setTolerancesSS(doublereal rtol, doublereal atol) { for (size_t n = 0; n < m_nv; n++) { m_rtol_ss[n] = rtol; m_atol_ss[n] = atol; } } void Domain1D:: eval(size_t jg, doublereal* xg, doublereal* rg, integer* mask, doublereal rdt) { if (jg != npos && (jg + 1 < firstPoint() || jg > lastPoint() + 1)) { return; } // if evaluating a Jacobian, compute the steady-state residual if (jg != npos) { rdt = 0.0; } // start of local part of global arrays doublereal* x = xg + loc(); doublereal* rsd = rg + loc(); integer* diag = mask + loc(); size_t jmin, jmax, jpt, j, i; jpt = jg - firstPoint(); if (jg == npos) { // evaluate all points jmin = 0; jmax = m_points - 1; } else { // evaluate points for Jacobian jmin = std::max(jpt, 1) - 1; jmax = std::min(jpt+1,m_points-1); } for (j = jmin; j <= jmax; j++) { if (j == 0 || j == m_points - 1) { for (i = 0; i < m_nv; i++) { rsd[index(i,j)] = residual(x,i,j); diag[index(i,j)] = 0; } } else { for (i = 0; i < m_nv; i++) { rsd[index(i,j)] = residual(x,i,j) - timeDerivativeFlag(i)*rdt*(value(x,i,j) - prevSoln(i,j)); diag[index(i,j)] = timeDerivativeFlag(i); } } } } XML_Node& Domain1D::save(XML_Node& o, const doublereal* const sol) { XML_Node& d = o.addChild("domain"); d.addAttribute("points", nPoints()); d.addAttribute("components", nComponents()); d.addAttribute("id", id()); addFloatArray(d, "abstol_transient", nComponents(), &m_atol_ts[0]); addFloatArray(d, "reltol_transient", nComponents(), &m_rtol_ts[0]); addFloatArray(d, "abstol_steady", nComponents(), &m_atol_ss[0]); addFloatArray(d, "reltol_steady", nComponents(), &m_rtol_ss[0]); return d; } void Domain1D::restore(const XML_Node& dom, doublereal* soln, int loglevel) { vector_fp values; vector nodes; dom.getChildren("floatArray", nodes); for (size_t i = 0; i < nodes.size(); i++) { string title = nodes[i]->attrib("title"); getFloatArray(*nodes[i], values, false); if (values.size() != nComponents()) { throw CanteraError("Domain1D::restore", "Got an array of length " + int2str(values.size()) + " when one of length " + int2str(nComponents()) + "was expected."); } if (title == "abstol_transient") { m_atol_ts = values; } else if (title == "reltol_transient") { m_rtol_ts = values; } else if (title == "abstol_steady") { m_atol_ss = values; } else if (title == "reltol_steady") { m_rtol_ss = values; } else { throw CanteraError("Domain1D::restore", "Got an unexpected array, '" + title + "'"); } } } void Domain1D::setupGrid(size_t n, const doublereal* z) { if (n > 1) { resize(m_nv, n); for (size_t j = 0; j < m_points; j++) { m_z[j] = z[j]; } } } void drawline() { writelog("\n-------------------------------------" "------------------------------------------"); } void Domain1D::showSolution(const doublereal* x) { size_t nn = m_nv/5; size_t i, j, n; //char* buf = new char[100]; char buf[100]; doublereal v; for (i = 0; i < nn; i++) { drawline(); sprintf(buf, "\n z "); writelog(buf); for (n = 0; n < 5; n++) { sprintf(buf, " %10s ",componentName(i*5 + n).c_str()); writelog(buf); } drawline(); for (j = 0; j < m_points; j++) { sprintf(buf, "\n %10.4g ",m_z[j]); writelog(buf); for (n = 0; n < 5; n++) { v = value(x, i*5+n, j); sprintf(buf, " %10.4g ",v); writelog(buf); } } writelog("\n"); } size_t nrem = m_nv - 5*nn; drawline(); sprintf(buf, "\n z "); writelog(buf); for (n = 0; n < nrem; n++) { sprintf(buf, " %10s ", componentName(nn*5 + n).c_str()); writelog(buf); } drawline(); for (j = 0; j < m_points; j++) { sprintf(buf, "\n %10.4g ",m_z[j]); writelog(buf); for (n = 0; n < nrem; n++) { v = value(x, nn*5+n, j); sprintf(buf, " %10.4g ", v); writelog(buf); } } writelog("\n"); } void Domain1D::_getInitialSoln(doublereal* x) { for (size_t j = 0; j < m_points; j++) { for (size_t n = 0; n < m_nv; n++) { x[index(n,j)] = initialValue(n,j); } } } doublereal Domain1D::initialValue(size_t n, size_t j) { throw CanteraError("Domain1D::initialValue", "base class method called!"); return 0.0; } } // namespace