Merged Revisision_1.8.0 changes into the trunk.
This commit is contained in:
commit
15c9ca0294
7 changed files with 532 additions and 403 deletions
|
|
@ -25,7 +25,7 @@ using namespace std;
|
|||
|
||||
#else
|
||||
|
||||
#ifdef SUNDIALS_VERSION_23
|
||||
#if defined(SUNDIALS_VERSION_23) || defined (SUNDIALS_VERSION_24)
|
||||
#include <sundials/sundials_types.h>
|
||||
#include <sundials/sundials_math.h>
|
||||
#include <sundials/sundials_nvector.h>
|
||||
|
|
@ -42,383 +42,471 @@ unsupported sundials version!
|
|||
|
||||
#endif
|
||||
|
||||
#if defined (SUNDIALS_VERSION_24)
|
||||
#define CV_SS 1
|
||||
#define CV_SV 2
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
inline static N_Vector nv(void* x) {
|
||||
return reinterpret_cast<N_Vector>(x);
|
||||
return reinterpret_cast<N_Vector>(x);
|
||||
}
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class FuncData {
|
||||
public:
|
||||
FuncData(FuncEval* f, int npar = 0) {
|
||||
m_pars.resize(npar, 1.0);
|
||||
m_func = f;
|
||||
}
|
||||
virtual ~FuncData() {}
|
||||
vector_fp m_pars;
|
||||
FuncEval* m_func;
|
||||
};
|
||||
class FuncData {
|
||||
public:
|
||||
FuncData(FuncEval* f, int npar = 0) {
|
||||
m_pars.resize(npar, 1.0);
|
||||
m_func = f;
|
||||
}
|
||||
virtual ~FuncData() {}
|
||||
vector_fp m_pars;
|
||||
FuncEval* m_func;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
* Function called by cvodes to evaluate ydot given y. The cvode
|
||||
* integrator allows passing in a void* pointer to access
|
||||
* external data. This pointer is cast to a pointer to a instance
|
||||
* of class FuncEval. The equations to be integrated should be
|
||||
* specified by deriving a class from FuncEval that evaluates the
|
||||
* desired equations.
|
||||
* @ingroup odeGroup
|
||||
*/
|
||||
static int cvodes_rhs(realtype t, N_Vector y, N_Vector ydot,
|
||||
void *f_data) {
|
||||
double* ydata = NV_DATA_S(y); //N_VDATA(y);
|
||||
double* ydotdata = NV_DATA_S(ydot); //N_VDATA(ydot);
|
||||
Cantera::FuncData* d = (Cantera::FuncData*)f_data;
|
||||
Cantera::FuncEval* f = d->m_func;
|
||||
//try {
|
||||
if (d->m_pars.size() == 0)
|
||||
f->eval(t, ydata, ydotdata, NULL);
|
||||
else
|
||||
f->eval(t, ydata, ydotdata, DATA_PTR(d->m_pars));
|
||||
//}
|
||||
//catch (...) {
|
||||
//Cantera::showErrors();
|
||||
//Cantera::error("Teminating execution");
|
||||
//}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Function called by cvodes to evaluate ydot given y. The cvode
|
||||
* integrator allows passing in a void* pointer to access
|
||||
* external data. This pointer is cast to a pointer to a instance
|
||||
* of class FuncEval. The equations to be integrated should be
|
||||
* specified by deriving a class from FuncEval that evaluates the
|
||||
* desired equations.
|
||||
* @ingroup odeGroup
|
||||
*/
|
||||
static int cvodes_rhs(realtype t, N_Vector y, N_Vector ydot,
|
||||
void *f_data) {
|
||||
double* ydata = NV_DATA_S(y); //N_VDATA(y);
|
||||
double* ydotdata = NV_DATA_S(ydot); //N_VDATA(ydot);
|
||||
Cantera::FuncData* d = (Cantera::FuncData*)f_data;
|
||||
Cantera::FuncEval* f = d->m_func;
|
||||
//try {
|
||||
if (d->m_pars.size() == 0)
|
||||
f->eval(t, ydata, ydotdata, NULL);
|
||||
else
|
||||
f->eval(t, ydata, ydotdata, DATA_PTR(d->m_pars));
|
||||
//}
|
||||
//catch (...) {
|
||||
//Cantera::showErrors();
|
||||
//Cantera::error("Teminating execution");
|
||||
//}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/**
|
||||
* Constructor. Default settings: dense jacobian, no user-supplied
|
||||
* Jacobian function, Newton iteration.
|
||||
*/
|
||||
CVodesIntegrator::CVodesIntegrator() : m_neq(0),
|
||||
m_cvode_mem(0),
|
||||
m_t0(0.0),
|
||||
m_y(0),
|
||||
m_abstol(0),
|
||||
m_type(DENSE+NOJAC),
|
||||
m_itol(CV_SS),
|
||||
m_method(CV_BDF),
|
||||
m_iter(CV_NEWTON),
|
||||
m_maxord(0),
|
||||
m_reltol(1.e-9),
|
||||
m_abstols(1.e-15),
|
||||
m_reltolsens(1.0e-5),
|
||||
m_abstolsens(1.0e-4),
|
||||
m_nabs(0),
|
||||
m_hmax(0.0),
|
||||
m_maxsteps(20000), m_np(0),
|
||||
m_mupper(0), m_mlower(0)
|
||||
{
|
||||
//m_ropt.resize(OPT_SIZE,0.0);
|
||||
//m_iopt = new long[OPT_SIZE];
|
||||
//fill(m_iopt, m_iopt+OPT_SIZE,0);
|
||||
/**
|
||||
* Constructor. Default settings: dense jacobian, no user-supplied
|
||||
* Jacobian function, Newton iteration.
|
||||
*/
|
||||
CVodesIntegrator::CVodesIntegrator() :
|
||||
m_neq(0),
|
||||
m_cvode_mem(0),
|
||||
m_t0(0.0),
|
||||
m_y(0),
|
||||
m_abstol(0),
|
||||
m_type(DENSE+NOJAC),
|
||||
m_itol(CV_SS),
|
||||
m_method(CV_BDF),
|
||||
m_iter(CV_NEWTON),
|
||||
m_maxord(0),
|
||||
m_reltol(1.e-9),
|
||||
m_abstols(1.e-15),
|
||||
m_reltolsens(1.0e-5),
|
||||
m_abstolsens(1.0e-4),
|
||||
m_nabs(0),
|
||||
m_hmax(0.0),
|
||||
m_maxsteps(20000), m_np(0),
|
||||
m_mupper(0), m_mlower(0)
|
||||
{
|
||||
//m_ropt.resize(OPT_SIZE,0.0);
|
||||
//m_iopt = new long[OPT_SIZE];
|
||||
//fill(m_iopt, m_iopt+OPT_SIZE,0);
|
||||
}
|
||||
|
||||
|
||||
/// Destructor.
|
||||
CVodesIntegrator::~CVodesIntegrator()
|
||||
{
|
||||
if (m_cvode_mem) {
|
||||
if (m_np > 0)
|
||||
CVodeSensFree(m_cvode_mem);
|
||||
CVodeFree(&m_cvode_mem);
|
||||
}
|
||||
if (m_y) N_VDestroy_Serial(nv(m_y));
|
||||
if (m_abstol) N_VDestroy_Serial(nv(m_abstol));
|
||||
delete m_fdata;
|
||||
|
||||
|
||||
/// Destructor.
|
||||
CVodesIntegrator::~CVodesIntegrator()
|
||||
{
|
||||
if (m_cvode_mem) {
|
||||
if (m_np > 0)
|
||||
CVodeSensFree(m_cvode_mem);
|
||||
CVodeFree(&m_cvode_mem);
|
||||
}
|
||||
if (m_y) N_VDestroy_Serial(nv(m_y));
|
||||
if (m_abstol) N_VDestroy_Serial(nv(m_abstol));
|
||||
delete m_fdata;
|
||||
|
||||
//delete[] m_iopt;
|
||||
}
|
||||
//delete[] m_iopt;
|
||||
}
|
||||
|
||||
double& CVodesIntegrator::solution(int k){
|
||||
return NV_Ith_S(nv(m_y),k);
|
||||
}
|
||||
double& CVodesIntegrator::solution(int k){
|
||||
return NV_Ith_S(nv(m_y),k);
|
||||
}
|
||||
|
||||
double* CVodesIntegrator::solution(){ return NV_DATA_S(nv(m_y));
|
||||
double* CVodesIntegrator::solution(){ return NV_DATA_S(nv(m_y));
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setTolerances(double reltol, int n, double* abstol) {
|
||||
m_itol = CV_SV;
|
||||
m_nabs = n;
|
||||
if (n != m_neq) {
|
||||
if (m_abstol) N_VDestroy_Serial(nv(m_abstol));
|
||||
m_abstol = reinterpret_cast<void*>(N_VNew_Serial(n));
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setTolerances(double reltol, int n, double* abstol) {
|
||||
m_itol = CV_SV;
|
||||
m_nabs = n;
|
||||
if (n != m_neq) {
|
||||
if (m_abstol) N_VDestroy_Serial(nv(m_abstol));
|
||||
m_abstol = reinterpret_cast<void*>(N_VNew_Serial(n));
|
||||
}
|
||||
for (int i=0; i<n; i++) {
|
||||
NV_Ith_S(nv(m_abstol), i) = abstol[i];
|
||||
}
|
||||
m_reltol = reltol;
|
||||
for (int i=0; i<n; i++) {
|
||||
NV_Ith_S(nv(m_abstol), i) = abstol[i];
|
||||
}
|
||||
m_reltol = reltol;
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setTolerances(double reltol, double abstol) {
|
||||
m_itol = CV_SS;
|
||||
m_reltol = reltol;
|
||||
m_abstols = abstol;
|
||||
}
|
||||
void CVodesIntegrator::setTolerances(double reltol, double abstol) {
|
||||
m_itol = CV_SS;
|
||||
m_reltol = reltol;
|
||||
m_abstols = abstol;
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setSensitivityTolerances(double reltol, double abstol) {
|
||||
m_reltolsens = reltol;
|
||||
m_abstolsens = abstol;
|
||||
}
|
||||
void CVodesIntegrator::setSensitivityTolerances(double reltol, double abstol) {
|
||||
m_reltolsens = reltol;
|
||||
m_abstolsens = abstol;
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setProblemType(int probtype) {
|
||||
m_type = probtype;
|
||||
}
|
||||
void CVodesIntegrator::setProblemType(int probtype) {
|
||||
m_type = probtype;
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setMethod(MethodType t) {
|
||||
if (t == BDF_Method)
|
||||
m_method = CV_BDF;
|
||||
else if (t == Adams_Method)
|
||||
m_method = CV_ADAMS;
|
||||
else
|
||||
throw CVodesErr("unknown method");
|
||||
}
|
||||
void CVodesIntegrator::setMethod(MethodType t) {
|
||||
if (t == BDF_Method)
|
||||
m_method = CV_BDF;
|
||||
else if (t == Adams_Method)
|
||||
m_method = CV_ADAMS;
|
||||
else
|
||||
throw CVodesErr("unknown method");
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setMaxStepSize(doublereal hmax) {
|
||||
m_hmax = hmax;
|
||||
if (m_cvode_mem)
|
||||
CVodeSetMaxStep(m_cvode_mem, hmax);
|
||||
}
|
||||
void CVodesIntegrator::setMaxStepSize(doublereal hmax) {
|
||||
m_hmax = hmax;
|
||||
if (m_cvode_mem)
|
||||
CVodeSetMaxStep(m_cvode_mem, hmax);
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setMinStepSize(doublereal hmin) {
|
||||
m_hmin = hmin;
|
||||
if (m_cvode_mem)
|
||||
CVodeSetMinStep(m_cvode_mem, hmin);
|
||||
}
|
||||
void CVodesIntegrator::setMinStepSize(doublereal hmin) {
|
||||
m_hmin = hmin;
|
||||
if (m_cvode_mem)
|
||||
CVodeSetMinStep(m_cvode_mem, hmin);
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setMaxSteps(int nmax) {
|
||||
m_maxsteps = nmax;
|
||||
if (m_cvode_mem)
|
||||
CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
|
||||
}
|
||||
void CVodesIntegrator::setMaxSteps(int nmax) {
|
||||
m_maxsteps = nmax;
|
||||
if (m_cvode_mem)
|
||||
CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
|
||||
}
|
||||
|
||||
void CVodesIntegrator::setIterator(IterType t) {
|
||||
if (t == Newton_Iter)
|
||||
m_iter = CV_NEWTON;
|
||||
else if (t == Functional_Iter)
|
||||
m_iter = CV_FUNCTIONAL;
|
||||
else
|
||||
throw CVodesErr("unknown iterator");
|
||||
}
|
||||
void CVodesIntegrator::setIterator(IterType t) {
|
||||
if (t == Newton_Iter)
|
||||
m_iter = CV_NEWTON;
|
||||
else if (t == Functional_Iter)
|
||||
m_iter = CV_FUNCTIONAL;
|
||||
else
|
||||
throw CVodesErr("unknown iterator");
|
||||
}
|
||||
|
||||
void CVodesIntegrator::sensInit(double t0, FuncEval& func) {
|
||||
m_np = func.nparams();
|
||||
long int nv = func.neq();
|
||||
void CVodesIntegrator::sensInit(double t0, FuncEval& func) {
|
||||
m_np = func.nparams();
|
||||
long int nv = func.neq();
|
||||
|
||||
doublereal* data;
|
||||
int n, j;
|
||||
N_Vector y;
|
||||
y = N_VNew_Serial(nv);
|
||||
m_yS = N_VCloneVectorArray_Serial(m_np, y);
|
||||
for (n = 0; n < m_np; n++) {
|
||||
data = NV_DATA_S(m_yS[n]);
|
||||
for (j = 0; j < nv; j++) {
|
||||
data[j] =0.0;
|
||||
}
|
||||
}
|
||||
|
||||
int flag;
|
||||
flag = CVodeSensMalloc(m_cvode_mem, m_np, CV_STAGGERED, m_yS);
|
||||
if (flag != CV_SUCCESS)
|
||||
throw CVodesErr("Error in CVodeSensMalloc");
|
||||
vector_fp atol(m_np, m_abstolsens);
|
||||
double rtol = m_reltolsens;
|
||||
flag = CVodeSetSensTolerances(m_cvode_mem, CV_SS, rtol, DATA_PTR(atol));
|
||||
}
|
||||
|
||||
void CVodesIntegrator::initialize(double t0, FuncEval& func)
|
||||
{
|
||||
m_neq = func.neq();
|
||||
m_t0 = t0;
|
||||
|
||||
if (m_y) {
|
||||
N_VDestroy_Serial(nv(m_y)); // free solution vector if already allocated
|
||||
}
|
||||
m_y = reinterpret_cast<void*>(N_VNew_Serial(m_neq)); // allocate solution vector
|
||||
for (int i=0; i<m_neq; i++) {
|
||||
NV_Ith_S(nv(m_y), i) = 0.0;
|
||||
}
|
||||
// check abs tolerance array size
|
||||
if (m_itol == CV_SV && m_nabs < m_neq)
|
||||
throw CVodesErr("not enough absolute tolerance values specified.");
|
||||
|
||||
func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y)));
|
||||
|
||||
if (m_cvode_mem) CVodeFree(&m_cvode_mem);
|
||||
m_cvode_mem = CVodeCreate(m_method, m_iter);
|
||||
if (!m_cvode_mem) throw CVodesErr("CVodeCreate failed.");
|
||||
|
||||
int flag = 0;
|
||||
if (m_itol == CV_SV) {
|
||||
// vector atol
|
||||
flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol,
|
||||
m_reltol, nv(m_abstol));
|
||||
}
|
||||
else {
|
||||
// scalar atol
|
||||
flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol,
|
||||
m_reltol, &m_abstols);
|
||||
}
|
||||
if (flag != CV_SUCCESS) {
|
||||
if (flag == CV_MEM_FAIL) {
|
||||
throw CVodesErr("Memory allocation failed.");
|
||||
}
|
||||
else if (flag == CV_ILL_INPUT) {
|
||||
throw CVodesErr("Illegal value for CVodeMalloc input argument.");
|
||||
}
|
||||
else
|
||||
throw CVodesErr("CVodeMalloc failed.");
|
||||
}
|
||||
|
||||
|
||||
if (m_type == DENSE + NOJAC) {
|
||||
long int N = m_neq;
|
||||
CVDense(m_cvode_mem, N);
|
||||
}
|
||||
else if (m_type == DIAG) {
|
||||
CVDiag(m_cvode_mem);
|
||||
}
|
||||
else if (m_type == GMRES) {
|
||||
CVSpgmr(m_cvode_mem, PREC_NONE, 0);
|
||||
}
|
||||
else if (m_type == BAND + NOJAC) {
|
||||
long int N = m_neq;
|
||||
long int nu = m_mupper;
|
||||
long int nl = m_mlower;
|
||||
CVBand(m_cvode_mem, N, nu, nl);
|
||||
}
|
||||
else {
|
||||
throw CVodesErr("unsupported option");
|
||||
}
|
||||
|
||||
// pass a pointer to func in m_data
|
||||
m_fdata = new FuncData(&func, func.nparams());
|
||||
|
||||
//m_data = (void*)&func;
|
||||
|
||||
flag = CVodeSetFdata(m_cvode_mem, (void*)m_fdata);
|
||||
if (flag != CV_SUCCESS)
|
||||
throw CVodesErr("CVodeSetFdata failed.");
|
||||
|
||||
if (func.nparams() > 0) {
|
||||
sensInit(t0, func);
|
||||
flag = CVodeSetSensParams(m_cvode_mem, DATA_PTR(m_fdata->m_pars),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
// set options
|
||||
if (m_maxord > 0)
|
||||
flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord);
|
||||
if (m_maxsteps > 0)
|
||||
flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
|
||||
if (m_hmax > 0)
|
||||
flag = CVodeSetMaxStep(m_cvode_mem, m_hmax);
|
||||
}
|
||||
|
||||
|
||||
void CVodesIntegrator::reinitialize(double t0, FuncEval& func)
|
||||
{
|
||||
m_t0 = t0;
|
||||
//try {
|
||||
func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y)));
|
||||
//}
|
||||
//catch (CanteraError) {
|
||||
//showErrors();
|
||||
//error("Teminating execution");
|
||||
//}
|
||||
|
||||
int result, flag;
|
||||
if (m_itol == CV_SV) {
|
||||
result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y),
|
||||
m_itol, m_reltol,
|
||||
nv(m_abstol));
|
||||
}
|
||||
else {
|
||||
result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y),
|
||||
m_itol, m_reltol,
|
||||
&m_abstols);
|
||||
}
|
||||
if (result != CV_SUCCESS)
|
||||
throw CVodesErr("CVReInit failed. result = "+int2str(result));
|
||||
|
||||
if (m_type == DENSE + NOJAC) {
|
||||
long int N = m_neq;
|
||||
CVDense(m_cvode_mem, N);
|
||||
}
|
||||
else if (m_type == DIAG) {
|
||||
CVDiag(m_cvode_mem);
|
||||
}
|
||||
else if (m_type == BAND + NOJAC) {
|
||||
long int N = m_neq;
|
||||
long int nu = m_mupper;
|
||||
long int nl = m_mlower;
|
||||
CVBand(m_cvode_mem, N, nu, nl);
|
||||
}
|
||||
else if (m_type == GMRES) {
|
||||
CVSpgmr(m_cvode_mem, PREC_NONE, 0);
|
||||
}
|
||||
else {
|
||||
throw CVodesErr("unsupported option");
|
||||
}
|
||||
|
||||
|
||||
// set options
|
||||
if (m_maxord > 0)
|
||||
flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord);
|
||||
if (m_maxsteps > 0)
|
||||
flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
|
||||
if (m_hmax > 0)
|
||||
flag = CVodeSetMaxStep(m_cvode_mem, m_hmax);
|
||||
}
|
||||
|
||||
void CVodesIntegrator::integrate(double tout)
|
||||
{
|
||||
double t;
|
||||
int flag;
|
||||
flag = CVode(m_cvode_mem, tout, nv(m_y), &t, CV_NORMAL);
|
||||
if (flag != CV_SUCCESS)
|
||||
throw CVodesErr(" CVodes error encountered.");
|
||||
if (m_np > 0) {
|
||||
CVodeGetSens(m_cvode_mem, tout, m_yS);
|
||||
}
|
||||
}
|
||||
|
||||
double CVodesIntegrator::step(double tout)
|
||||
{
|
||||
double t;
|
||||
int flag;
|
||||
flag = CVode(m_cvode_mem, tout, nv(m_y), &t, CV_ONE_STEP);
|
||||
if (flag != CV_SUCCESS)
|
||||
throw CVodesErr(" CVodes error encountered.");
|
||||
return t;
|
||||
doublereal* data;
|
||||
int n, j;
|
||||
N_Vector y;
|
||||
y = N_VNew_Serial(nv);
|
||||
m_yS = N_VCloneVectorArray_Serial(m_np, y);
|
||||
for (n = 0; n < m_np; n++) {
|
||||
data = NV_DATA_S(m_yS[n]);
|
||||
for (j = 0; j < nv; j++) {
|
||||
data[j] =0.0;
|
||||
}
|
||||
|
||||
int CVodesIntegrator::nEvals() const {
|
||||
long int ne;
|
||||
CVodeGetNumRhsEvals(m_cvode_mem, &ne);
|
||||
return ne;
|
||||
//return m_iopt[NFE];
|
||||
}
|
||||
|
||||
double CVodesIntegrator::sensitivity(int k, int p) {
|
||||
if (k < 0 || k >= m_neq)
|
||||
throw CVodesErr("sensitivity: k out of range ("+int2str(p)+")");
|
||||
if (p < 0 || p >= m_np)
|
||||
throw CVodesErr("sensitivity: p out of range ("+int2str(p)+")");
|
||||
return NV_Ith_S(m_yS[p],k);
|
||||
int flag;
|
||||
|
||||
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION23)
|
||||
flag = CVodeSensMalloc(m_cvode_mem, m_np, CV_STAGGERED, m_yS);
|
||||
if (flag != CV_SUCCESS) {
|
||||
throw CVodesErr("Error in CVodeSensMalloc");
|
||||
}
|
||||
vector_fp atol(m_np, m_abstolsens);
|
||||
double rtol = m_reltolsens;
|
||||
flag = CVodeSetSensTolerances(m_cvode_mem, CV_SS, rtol, DATA_PTR(atol));
|
||||
#elif defined(SUNDIALS_VERSION_24)
|
||||
flag = CVodeSensInit(m_cvode_mem, m_np, CV_STAGGERED,
|
||||
CVSensRhsFn (0), m_yS);
|
||||
|
||||
if (flag != CV_SUCCESS) {
|
||||
throw CVodesErr("Error in CVodeSensMalloc");
|
||||
}
|
||||
vector_fp atol(m_np, m_abstolsens);
|
||||
double rtol = m_reltolsens;
|
||||
flag = CVodeSensSStolerances(m_cvode_mem, rtol, DATA_PTR(atol));
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void CVodesIntegrator::initialize(double t0, FuncEval& func)
|
||||
{
|
||||
m_neq = func.neq();
|
||||
m_t0 = t0;
|
||||
|
||||
if (m_y) {
|
||||
N_VDestroy_Serial(nv(m_y)); // free solution vector if already allocated
|
||||
}
|
||||
m_y = reinterpret_cast<void*>(N_VNew_Serial(m_neq)); // allocate solution vector
|
||||
for (int i=0; i<m_neq; i++) {
|
||||
NV_Ith_S(nv(m_y), i) = 0.0;
|
||||
}
|
||||
// check abs tolerance array size
|
||||
if (m_itol == CV_SV && m_nabs < m_neq)
|
||||
throw CVodesErr("not enough absolute tolerance values specified.");
|
||||
|
||||
func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y)));
|
||||
|
||||
if (m_cvode_mem) CVodeFree(&m_cvode_mem);
|
||||
|
||||
/*
|
||||
* Specify the method and the iteration type:
|
||||
* Cantera Defaults:
|
||||
* CV_BDF - Use BDF methods
|
||||
* CV_NEWTON - use newton's method
|
||||
*/
|
||||
m_cvode_mem = CVodeCreate(m_method, m_iter);
|
||||
if (!m_cvode_mem) throw CVodesErr("CVodeCreate failed.");
|
||||
|
||||
int flag = 0;
|
||||
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION23)
|
||||
if (m_itol == CV_SV) {
|
||||
// vector atol
|
||||
flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol,
|
||||
m_reltol, nv(m_abstol));
|
||||
}
|
||||
else {
|
||||
// scalar atol
|
||||
flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol,
|
||||
m_reltol, &m_abstols);
|
||||
}
|
||||
if (flag != CV_SUCCESS) {
|
||||
if (flag == CV_MEM_FAIL) {
|
||||
throw CVodesErr("Memory allocation failed.");
|
||||
}
|
||||
else if (flag == CV_ILL_INPUT) {
|
||||
throw CVodesErr("Illegal value for CVodeMalloc input argument.");
|
||||
}
|
||||
else
|
||||
throw CVodesErr("CVodeMalloc failed.");
|
||||
}
|
||||
#elif defined(SUNDIALS_VERSION_24)
|
||||
|
||||
flag = CVodeInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y));
|
||||
if (flag != CV_SUCCESS) {
|
||||
if (flag == CV_MEM_FAIL) {
|
||||
throw CVodesErr("Memory allocation failed.");
|
||||
} else if (flag == CV_ILL_INPUT) {
|
||||
throw CVodesErr("Illegal value for CVodeInit input argument.");
|
||||
} else {
|
||||
throw CVodesErr("CVodeInit failed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_itol == CV_SV) {
|
||||
flag = CVodeSVtolerances(m_cvode_mem, m_reltol, nv(m_abstol));
|
||||
} else {
|
||||
flag = CVodeSStolerances(m_cvode_mem, m_reltol, m_abstols);
|
||||
}
|
||||
if (flag != CV_SUCCESS) {
|
||||
if (flag == CV_MEM_FAIL) {
|
||||
throw CVodesErr("Memory allocation failed.");
|
||||
} else if (flag == CV_ILL_INPUT) {
|
||||
throw CVodesErr("Illegal value for CVodeInit input argument.");
|
||||
} else {
|
||||
throw CVodesErr("CVodeInit failed.");
|
||||
}
|
||||
}
|
||||
#else
|
||||
printf("unknown sundials verson\n");
|
||||
exit(-1);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (m_type == DENSE + NOJAC) {
|
||||
long int N = m_neq;
|
||||
CVDense(m_cvode_mem, N);
|
||||
}
|
||||
else if (m_type == DIAG) {
|
||||
CVDiag(m_cvode_mem);
|
||||
}
|
||||
else if (m_type == GMRES) {
|
||||
CVSpgmr(m_cvode_mem, PREC_NONE, 0);
|
||||
}
|
||||
else if (m_type == BAND + NOJAC) {
|
||||
long int N = m_neq;
|
||||
long int nu = m_mupper;
|
||||
long int nl = m_mlower;
|
||||
CVBand(m_cvode_mem, N, nu, nl);
|
||||
}
|
||||
else {
|
||||
throw CVodesErr("unsupported option");
|
||||
}
|
||||
|
||||
// pass a pointer to func in m_data
|
||||
m_fdata = new FuncData(&func, func.nparams());
|
||||
|
||||
//m_data = (void*)&func;
|
||||
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION23)
|
||||
flag = CVodeSetFdata(m_cvode_mem, (void*)m_fdata);
|
||||
if (flag != CV_SUCCESS) {
|
||||
throw CVodesErr("CVodeSetFdata failed.");
|
||||
}
|
||||
#elif defined(SUNDIALS_VERSION_24)
|
||||
flag = CVodeSetUserData(m_cvode_mem, (void*)m_fdata);
|
||||
if (flag != CV_SUCCESS) {
|
||||
throw CVodesErr("CVodeSetUserData failed.");
|
||||
}
|
||||
#endif
|
||||
if (func.nparams() > 0) {
|
||||
sensInit(t0, func);
|
||||
flag = CVodeSetSensParams(m_cvode_mem, DATA_PTR(m_fdata->m_pars),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
// set options
|
||||
if (m_maxord > 0)
|
||||
flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord);
|
||||
if (m_maxsteps > 0)
|
||||
flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
|
||||
if (m_hmax > 0)
|
||||
flag = CVodeSetMaxStep(m_cvode_mem, m_hmax);
|
||||
}
|
||||
|
||||
|
||||
void CVodesIntegrator::reinitialize(double t0, FuncEval& func)
|
||||
{
|
||||
m_t0 = t0;
|
||||
//try {
|
||||
func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y)));
|
||||
//}
|
||||
//catch (CanteraError) {
|
||||
//showErrors();
|
||||
//error("Teminating execution");
|
||||
//}
|
||||
|
||||
int result, flag;
|
||||
|
||||
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION23)
|
||||
if (m_itol == CV_SV) {
|
||||
result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y),
|
||||
m_itol, m_reltol,
|
||||
nv(m_abstol));
|
||||
}
|
||||
else {
|
||||
result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y),
|
||||
m_itol, m_reltol,
|
||||
&m_abstols);
|
||||
}
|
||||
if (result != CV_SUCCESS) {
|
||||
throw CVodesErr("CVodeReInit failed. result = "+int2str(result));
|
||||
}
|
||||
#elif defined(SUNDIALS_VERSION_24)
|
||||
result = CVodeReInit(m_cvode_mem, m_t0, nv(m_y));
|
||||
if (result != CV_SUCCESS) {
|
||||
throw CVodesErr("CVodeReInit failed. result = "+int2str(result));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_type == DENSE + NOJAC) {
|
||||
long int N = m_neq;
|
||||
CVDense(m_cvode_mem, N);
|
||||
}
|
||||
else if (m_type == DIAG) {
|
||||
CVDiag(m_cvode_mem);
|
||||
}
|
||||
else if (m_type == BAND + NOJAC) {
|
||||
long int N = m_neq;
|
||||
long int nu = m_mupper;
|
||||
long int nl = m_mlower;
|
||||
CVBand(m_cvode_mem, N, nu, nl);
|
||||
}
|
||||
else if (m_type == GMRES) {
|
||||
CVSpgmr(m_cvode_mem, PREC_NONE, 0);
|
||||
}
|
||||
else {
|
||||
throw CVodesErr("unsupported option");
|
||||
}
|
||||
|
||||
|
||||
// set options
|
||||
if (m_maxord > 0)
|
||||
flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord);
|
||||
if (m_maxsteps > 0)
|
||||
flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
|
||||
if (m_hmax > 0)
|
||||
flag = CVodeSetMaxStep(m_cvode_mem, m_hmax);
|
||||
}
|
||||
|
||||
void CVodesIntegrator::integrate(double tout)
|
||||
{
|
||||
double t;
|
||||
int flag;
|
||||
double tretn;
|
||||
flag = CVode(m_cvode_mem, tout, nv(m_y), &t, CV_NORMAL);
|
||||
if (flag != CV_SUCCESS)
|
||||
throw CVodesErr(" CVodes error encountered.");
|
||||
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION23)
|
||||
if (m_np > 0) {
|
||||
CVodeGetSens(m_cvode_mem, tout, m_yS);
|
||||
}
|
||||
#elif defined(SUNDIALS_VERSION_24)
|
||||
if (m_np > 0) {
|
||||
CVodeGetSens(m_cvode_mem, &tretn, m_yS);
|
||||
if (fabs(tretn - tout) > 1.0E-5) {
|
||||
throw CVodesErr("Time of Sensitivities different than time of tout");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
double CVodesIntegrator::step(double tout)
|
||||
{
|
||||
double t;
|
||||
int flag;
|
||||
flag = CVode(m_cvode_mem, tout, nv(m_y), &t, CV_ONE_STEP);
|
||||
if (flag != CV_SUCCESS)
|
||||
throw CVodesErr(" CVodes error encountered.");
|
||||
return t;
|
||||
}
|
||||
|
||||
int CVodesIntegrator::nEvals() const {
|
||||
long int ne;
|
||||
CVodeGetNumRhsEvals(m_cvode_mem, &ne);
|
||||
return ne;
|
||||
//return m_iopt[NFE];
|
||||
}
|
||||
|
||||
double CVodesIntegrator::sensitivity(int k, int p) {
|
||||
if (k < 0 || k >= m_neq)
|
||||
throw CVodesErr("sensitivity: k out of range ("+int2str(p)+")");
|
||||
if (p < 0 || p >= m_np)
|
||||
throw CVodesErr("sensitivity: p out of range ("+int2str(p)+")");
|
||||
return NV_Ith_S(m_yS[p],k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ typedef int ftnlen; // Fortran hidden string length type
|
|||
#undef HAS_SUNDIALS
|
||||
#undef SUNDIALS_VERSION_22
|
||||
#undef SUNDIALS_VERSION_23
|
||||
#undef SUNDIALS_VERSION_24
|
||||
|
||||
//-------- LAPACK / BLAS ---------
|
||||
|
||||
|
|
|
|||
74
configure
vendored
74
configure
vendored
File diff suppressed because one or more lines are too long
48
configure.in
48
configure.in
|
|
@ -365,29 +365,45 @@ sundials_lib_dep=
|
|||
|
||||
|
||||
if test ${use_sundials} = 1; then
|
||||
AC_DEFINE(HAS_SUNDIALS)
|
||||
echo "using CVODES from SUNDIALS... Sensitivity analysis enabled."
|
||||
|
||||
CVODE_LIBS='-lsundials_cvodes -lsundials_nvecserial'
|
||||
IDA_LIBS='-lsundials_ida -lsundials_nvecserial'
|
||||
|
||||
if test "$SUNDIALS_VERSION" = "2.2"; then
|
||||
AC_DEFINE(SUNDIALS_VERSION_22)
|
||||
sundials_include='-I'${SUNDIALS_HOME}'/include -I'${SUNDIALS_HOME}'/include/sundials -I'${SUNDIALS_HOME}'/include/cvodes -I'${SUNDIALS_HOME}'/include/ida'
|
||||
echo "sundials include directory: " ${sundials_include}
|
||||
echo "sundials library directory: " $SUNDIALS_LIB_DIR
|
||||
sundials_lib_dir=$SUNDIALS_LIB_DIR
|
||||
sundials_lib="-L$SUNDIALS_LIB_DIR -lsundials_cvodes -lsundials_ida -lsundials_nvecserial"
|
||||
sundials_lib_dep="$SUNDIALS_LIB_DIR/libsundials_cvodes.a $SUNDIALS_LIB_DIR/libsundials_ida.a $SUNDIALS_LIB_DIR/libsundials_nvecserial.a"
|
||||
AC_DEFINE(HAS_SUNDIALS)
|
||||
AC_DEFINE(SUNDIALS_VERSION_22)
|
||||
sundials_include='-I'${SUNDIALS_HOME}'/include -I'${SUNDIALS_HOME}'/include/sundials -I'${SUNDIALS_HOME}'/include/cvodes -I'${SUNDIALS_HOME}'/include/ida'
|
||||
echo "sundials include directory: " ${sundials_include}
|
||||
echo "sundials library directory: " $SUNDIALS_LIB_DIR
|
||||
sundials_lib_dir=$SUNDIALS_LIB_DIR
|
||||
sundials_lib="-L$SUNDIALS_LIB_DIR -lsundials_cvodes -lsundials_ida -lsundials_nvecserial"
|
||||
sundials_lib_dep="$SUNDIALS_LIB_DIR/libsundials_cvodes.a $SUNDIALS_LIB_DIR/libsundials_ida.a $SUNDIALS_LIB_DIR/libsundials_nvecserial.a"
|
||||
elif test "$SUNDIALS_VERSION" = "2.3"; then
|
||||
AC_DEFINE(HAS_SUNDIALS)
|
||||
AC_DEFINE(SUNDIALS_VERSION_23)
|
||||
sundials_include='-I'${SUNDIALS_INC_DIR}
|
||||
echo "sundials include directory: " ${sundials_include}
|
||||
echo "sundials library directory: " $SUNDIALS_LIB_DIR
|
||||
sundials_lib_dir=$SUNDIALS_LIB_DIR
|
||||
sundials_lib="-L$SUNDIALS_LIB_DIR -lsundials_cvodes -lsundials_ida -lsundials_nvecserial"
|
||||
sundials_lib_dep="$SUNDIALS_LIB_DIR/libsundials_cvodes.a $SUNDIALS_LIB_DIR/libsundials_ida.a $SUNDIALS_LIB_DIR/libsundials_nvecserial.a"
|
||||
# python tools/src/sundials_version.py $SUNDIALS_HOME
|
||||
elif test "$SUNDIALS_VERSION" = "2.4"; then
|
||||
AC_DEFINE(HAS_SUNDIALS)
|
||||
AC_DEFINE(SUNDIALS_VERSION_24)
|
||||
sundials_include='-I'${SUNDIALS_INC_DIR}
|
||||
echo "sundials include directory: " ${sundials_include}
|
||||
echo "sundials library directory: " $SUNDIALS_LIB_DIR
|
||||
sundials_lib_dir=$SUNDIALS_LIB_DIR
|
||||
sundials_lib="-L$SUNDIALS_LIB_DIR -lsundials_cvodes -lsundials_ida -lsundials_nvecserial"
|
||||
sundials_lib_dep="$SUNDIALS_LIB_DIR/libsundials_cvodes.a $SUNDIALS_LIB_DIR/libsundials_ida.a $SUNDIALS_LIB_DIR/libsundials_nvecserial.a"
|
||||
# python tools/src/sundials_version.py $SUNDIALS_HOME
|
||||
else
|
||||
AC_DEFINE(SUNDIALS_VERSION_23)
|
||||
sundials_include='-I'${SUNDIALS_INC_DIR}
|
||||
echo "sundials include directory: " ${sundials_include}
|
||||
echo "sundials library directory: " $SUNDIALS_LIB_DIR
|
||||
sundials_lib_dir=$SUNDIALS_LIB_DIR
|
||||
sundials_lib="-L$SUNDIALS_LIB_DIR -lsundials_cvodes -lsundials_ida -lsundials_nvecserial"
|
||||
sundials_lib_dep="$SUNDIALS_LIB_DIR/libsundials_cvodes.a $SUNDIALS_LIB_DIR/libsundials_ida.a $SUNDIALS_LIB_DIR/libsundials_nvecserial.a"
|
||||
# python tools/src/sundials_version.py $SUNDIALS_HOME
|
||||
echo "ERROR: unknown or unsupported sundials version #: $SUNDIALS_VERSION"
|
||||
echo " Supported versions are 2.2, 2.3, and 2.4"
|
||||
echo " Please fix or turn off the sundials option by setting USE_SUNDIALS to no"
|
||||
use_sundials=0
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -315,11 +315,11 @@ USE_SUNDIALS=${USE_SUNDIALS:='default'}
|
|||
|
||||
|
||||
# It is recommended that you install the newest release of sundials
|
||||
# (currently 2.3.0) before building Cantera. But if you want to use an
|
||||
# (currently 2.4.0) before building Cantera. But if you want to use an
|
||||
# older version, set SUNDIALS_VERSION to the version you have.
|
||||
# Acceptable values are '2.2' and '2.3' only; anything else will cause
|
||||
# Cantera to not use sundials.
|
||||
SUNDIALS_VERSION=${SUNDIALS_VERSION:='2.3'}
|
||||
# Acceptable values are '2.2', '2.3', or '2.4' ; anything else will cause
|
||||
# Cantera to
|
||||
SUNDIALS_VERSION=${SUNDIALS_VERSION:='2.4'}
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
# BLAS and LAPACK
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ Number of reactions = 8
|
|||
3 4.8454e-06 3.0554e-06 6.8484e+04 4.0505e+04 Csoot-*
|
||||
4 2.6364e-05 2.1519e-05 1.1250e+04 5.8320e+03 Csoot-*
|
||||
5 1.3012e-03 1.2749e-03 1.4427e+03 7.3573e+02 Csoot-*
|
||||
6 4.7372e+00 4.7359e+00 5.8161e-01 2.9647e-01 Csoot-*
|
||||
7 6.1771e-08 3.1736e-08
|
||||
FIN 7 6.1771e-08 2.1591e-11 -- success
|
||||
6 4.7372e+00 4.7359e+00 5.8160e-01 2.9647e-01 Csoot-*
|
||||
7 6.4112e-08 3.2378e-08
|
||||
FIN 7 6.4112e-08 3.6822e-12 -- success
|
||||
Gas Temperature = 1.4e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
@ -81,8 +81,8 @@ Sum of coverages = 1
|
|||
Iter Time Del_t Damp DelX Resid Name-Time Name-Damp
|
||||
-----------------------------------------------------------------------------------
|
||||
1 5.3218e+03 2.7005e+03
|
||||
2 8.9325e-06 4.0777e-06
|
||||
FIN 2 8.9325e-06 6.2499e-12 -- success
|
||||
2 8.8765e-06 4.0574e-06
|
||||
FIN 2 8.8765e-06 8.4527e-11 -- success
|
||||
Gas Temperature = 1.4e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
@ -140,8 +140,8 @@ Sum of coverages = 1
|
|||
Iter Time Del_t Damp DelX Resid Name-Time Name-Damp
|
||||
-----------------------------------------------------------------------------------
|
||||
1 2.1569e+05 9.5571e+04
|
||||
2 1.7622e-04 2.0108e-04
|
||||
FIN 2 1.7622e-04 2.0335e-10 -- success
|
||||
2 7.8671e-04 4.6185e-04
|
||||
FIN 2 7.8671e-04 1.5306e-10 -- success
|
||||
Gas Temperature = 1.5e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
@ -198,8 +198,8 @@ Sum of coverages = 1
|
|||
|
||||
Iter Time Del_t Damp DelX Resid Name-Time Name-Damp
|
||||
-----------------------------------------------------------------------------------
|
||||
1 2.8875e-10 1.4792e-10
|
||||
FIN 1 2.8875e-10 1.2324e-10 -- success
|
||||
1 3.0635e-10 1.5694e-10
|
||||
FIN 1 3.0635e-10 1.2314e-10 -- success
|
||||
Gas Temperature = 1.5e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ Number of reactions = 8
|
|||
3 4.8454e-06 3.0554e-06 6.8484e+04 4.0505e+04 Csoot-*
|
||||
4 2.6364e-05 2.1519e-05 1.1250e+04 5.8320e+03 Csoot-*
|
||||
5 1.3012e-03 1.2749e-03 1.4427e+03 7.3573e+02 Csoot-*
|
||||
6 4.7372e+00 4.7359e+00 5.8161e-01 2.9647e-01 Csoot-*
|
||||
7 6.1771e-08 3.1736e-08
|
||||
FIN 7 6.1771e-08 2.1591e-11 -- success
|
||||
6 4.7372e+00 4.7359e+00 5.8160e-01 2.9647e-01 Csoot-*
|
||||
7 6.4112e-08 3.2378e-08
|
||||
FIN 7 6.4112e-08 3.6822e-12 -- success
|
||||
Gas Temperature = 1.4e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
@ -72,8 +72,8 @@ Sum of coverages = 1
|
|||
Iter Time Del_t Damp DelX Resid Name-Time Name-Damp
|
||||
-----------------------------------------------------------------------------------
|
||||
1 5.3218e+03 2.7005e+03
|
||||
2 8.9325e-06 4.0777e-06
|
||||
FIN 2 8.9325e-06 6.2499e-12 -- success
|
||||
2 8.8765e-06 4.0574e-06
|
||||
FIN 2 8.8765e-06 8.4527e-11 -- success
|
||||
Gas Temperature = 1.4e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
@ -124,8 +124,8 @@ Sum of coverages = 1
|
|||
Iter Time Del_t Damp DelX Resid Name-Time Name-Damp
|
||||
-----------------------------------------------------------------------------------
|
||||
1 2.1569e+05 9.5571e+04
|
||||
2 1.7622e-04 2.0108e-04
|
||||
FIN 2 1.7622e-04 2.0335e-10 -- success
|
||||
2 7.8671e-04 4.6185e-04
|
||||
FIN 2 7.8671e-04 1.5306e-10 -- success
|
||||
Gas Temperature = 1.5e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
@ -175,8 +175,8 @@ Sum of coverages = 1
|
|||
|
||||
Iter Time Del_t Damp DelX Resid Name-Time Name-Damp
|
||||
-----------------------------------------------------------------------------------
|
||||
1 2.8875e-10 1.4792e-10
|
||||
FIN 1 2.8875e-10 1.2324e-10 -- success
|
||||
1 3.0635e-10 1.5694e-10
|
||||
FIN 1 3.0635e-10 1.2314e-10 -- success
|
||||
Gas Temperature = 1.5e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue