[SCons/Numerics] Use ext/sundials if system Sundials not installed

This commit is contained in:
Ray Speth 2015-11-13 14:55:53 -05:00
parent 34e38ab007
commit b4a1fb2db1
18 changed files with 99 additions and 561 deletions

View file

@ -408,19 +408,11 @@ config_options = [
"""Command to use for building the Sphinx documentation.""",
'sphinx-build', PathVariable.PathAccept),
EnumVariable(
'use_sundials',
"""Cantera uses the CVODE or CVODES ODE integrator to time-integrate
reactor network ODE's and for various other purposes. An older
version of CVODE comes with Cantera, but it is possible to use the
latest version as well, which now supports sensitivity analysis
(CVODES). CVODES is a part of the 'sundials' package from Lawrence
Livermore National Laboratory. Sundials is not distributed with
Cantera, but it is free software that may be downloaded and
installed separately. If you leave USE_SUNDIALS = 'default', then it
will be used if you have it, and if not the older CVODE will be
used. Or set USE_SUNDIALS to 'y' or 'n' to force using it or not.
Note that sensitivity analysis with Cantera requires use of
sundials. See: http://www.llnl.gov/CASC/sundials.""",
'system_sundials',
"""Select whether to use Sundials from a system installation ('y'), from
a git submodule ('n'), or to decide automatically ('default').
Specifying 'sundials_include' or 'sundials_libdir' changes the
default to 'y'.""",
'default', ('default', 'y', 'n')),
PathVariable(
'sundials_include',
@ -435,16 +427,6 @@ config_options = [
Not needed if the libraries are installed in a standard location,
e.g. /usr/lib.""",
'', PathVariable.PathAccept),
PathVariable(
'sundials_license',
"""Path to the sundials LICENSE file. Needed so that it can be included
when bundling Sundials.""",
'', PathVariable.PathAccept),
BoolVariable(
'install_sundials',
"""Determines whether Sundials library and header files are installed
alongside Cantera. Intended for use when installing on Windows.""",
os.name == 'nt'),
('blas_lapack_libs',
"""Cantera comes with Fortran (or C) versions of those parts of BLAS and
LAPACK it requires. But performance may be better if you use a version
@ -662,16 +644,13 @@ if env['boost_inc_dir']:
if env['blas_lapack_dir']:
env.Append(LIBPATH=[env['blas_lapack_dir']])
if (env['use_sundials'] == 'default' and
(env['sundials_include'] or env['sundials_libdir'])):
env['use_sundials'] = 'y'
if env['use_sundials'] in ('y','default'):
if env['system_sundials'] in ('y','default'):
if env['sundials_include']:
env.Append(CPPPATH=[env['sundials_include']])
env['system_sundials'] = 'y'
if env['sundials_libdir']:
env.Append(LIBPATH=[env['sundials_libdir']])
env['system_sundials'] = 'y'
# BLAS / LAPACK configuration
if env['blas_lapack_libs'] != '':
@ -821,12 +800,42 @@ ret = SCons.Conftest.CheckLib(context,
call='CVodeCreate(CV_BDF, CV_NEWTON);',
autoadd=False,
extra_libs=env['blas_lapack_libs'])
env['HAS_SUNDIALS'] = not ret # CheckLib returns False to indicate success
if ret:
# CheckLib returns False to indicate success
if env['system_sundials'] == 'default':
env['system_sundials'] = 'n'
elif env['system_sundials'] == 'y':
config_error('Expected system installation of Sundials, but it could '
'not be found.')
elif env['system_sundials'] == 'default':
env['system_sundials'] = 'y'
# Checkout Sundials submodule if needed
if (env['system_sundials'] == 'n' and
not os.path.exists('ext/sundials/include/cvodes/cvodes.h')):
if not os.path.exists('.git'):
config_error('Sundials is missing. Install source in ext/sundials.')
try:
code = subprocess.call(['git','submodule','update','--init',
'--recursive','ext/sundials'])
except Exception:
code = -1
if code:
config_error('Sundials not found and submodule checkout failed.\n'
'Try manually checking out the submodule with:\n\n'
' git submodule update --init --recursive ext/sundials\n')
env['NEED_LIBM'] = not conf.CheckLibWithHeader(None, 'math.h', 'C',
'double x; log(x);', False)
env['LIBM'] = ['m'] if env['NEED_LIBM'] else []
if env['HAS_SUNDIALS'] and env['use_sundials'] != 'n':
if env['system_sundials'] == 'y':
for subdir in ('sundials','nvector','cvodes','ida'):
removeDirectory('include/cantera/ext/'+subdir)
# Determine Sundials version
sundials_version_source = get_expression_value(['"sundials/sundials_config.h"'],
'QUOTE(SUNDIALS_PACKAGE_VERSION)')
@ -837,7 +846,10 @@ if env['HAS_SUNDIALS'] and env['use_sundials'] != 'n':
# Ignore the minor version, e.g. 2.4.x -> 2.4
env['sundials_version'] = '.'.join(sundials_version.split('.')[:2])
print """INFO: Using Sundials version %s.""" % sundials_version
if env['sundials_version'] not in ('2.4','2.5','2.6'):
print """ERROR: Sundials version %r is not supported.""" % env['sundials_version']
sys.exit(1)
print """INFO: Using system installation of Sundials version %s.""" % sundials_version
#Determine whether or not Sundials was built with BLAS/LAPACK
if LooseVersion(env['sundials_version']) < LooseVersion('2.6'):
@ -858,6 +870,11 @@ if env['HAS_SUNDIALS'] and env['use_sundials'] != 'n':
if not env['has_sundials_lapack'] and not env['BUILD_BLAS_LAPACK']:
print ('WARNING: External BLAS/LAPACK has been specified for Cantera '
'but Sundials was built without this support.')
else: # env['system_sundials'] == 'n'
print """INFO: Using private installation of Sundials version 2.6."""
env['sundials_version'] = '2.6'
env['has_sundials_lapack'] = int(not env['BUILD_BLAS_LAPACK'])
# Try to find a working Fortran compiler:
env['FORTRANSYSLIBS'] = []
@ -1073,19 +1090,6 @@ if env['matlab_toolbox'] == 'y':
sys.exit(1)
# Sundials Settings
if env['use_sundials'] == 'default':
if env['HAS_SUNDIALS']:
env['use_sundials'] = 'y'
else:
print "INFO: Sundials was not found. Building with minimal ODE solver capabilities."
env['use_sundials'] = 'n'
elif env['use_sundials'] == 'y' and not env['HAS_SUNDIALS']:
config_error("Unable to find Sundials headers and / or libraries.")
elif env['use_sundials'] == 'y' and env['sundials_version'] not in ('2.4','2.5','2.6'):
print """ERROR: Sundials version %r is not supported.""" % env['sundials_version']
sys.exit(1)
# **********************************************
# *** Set additional configuration variables ***
# **********************************************
@ -1206,11 +1210,7 @@ if env['python_package'] == 'none' and env['python3_package'] == 'n':
else:
configh['HAS_NO_PYTHON'] = None
cdefine('HAS_SUNDIALS', 'use_sundials', 'y')
if env['use_sundials'] == 'y':
configh['SUNDIALS_VERSION'] = env['sundials_version'].replace('.','')
else:
configh['SUNDIALS_VERSION'] = 0
configh['SUNDIALS_VERSION'] = env['sundials_version'].replace('.','')
if env.get('has_sundials_lapack') and not env['BUILD_BLAS_LAPACK']:
configh['SUNDIALS_USE_LAPACK'] = 1
@ -1295,18 +1295,6 @@ if addInstallActions:
# Data files
install('$inst_datadir', mglob(env, 'build/data', 'cti', 'xml'))
# Copy sundials library and header files
if env['install_sundials']:
for subdir in ['cvode','cvodes','ida','idas','kinsol','nvector','sundials']:
if os.path.exists(pjoin(env['sundials_include'], subdir)):
install(env.RecursiveInstall, pjoin('$inst_incdir', '..', subdir),
pjoin(env['sundials_include'], subdir))
if os.path.exists(env['sundials_license']):
install('$inst_incdir/../sundials', env['sundials_license'])
libprefix = '' if os.name == 'nt' else 'lib'
install('$inst_libdir', mglob(env, env['sundials_libdir'],
'^{0}sundials_*'.format(libprefix)))
### List of libraries needed to link to Cantera ###
linkLibs = ['cantera']
@ -1314,7 +1302,7 @@ linkLibs = ['cantera']
### List of shared libraries needed to link applications to Cantera
linkSharedLibs = ['cantera_shared']
if env['use_sundials'] == 'y':
if env['system_sundials'] == 'y':
env['sundials_libs'] = ['sundials_cvodes', 'sundials_ida', 'sundials_nvecserial']
linkLibs.extend(('sundials_cvodes', 'sundials_ida', 'sundials_nvecserial'))
linkSharedLibs.extend(('sundials_cvodes', 'sundials_ida', 'sundials_nvecserial'))

View file

@ -505,8 +505,8 @@ Optional Programs
* Sundials
* Required to enable some features such as sensitivity analysis.
* Strongly recommended if using reactor network or 1D simulation capabilities.
* Optional. If Sundials is not installed, it will be automatically downloaded
and the necessary portions will be compiled and installed with Cantera.
* https://computation.llnl.gov/casc/sundials/download/download.html
* Known to work with versions 2.4, 2.5 and 2.6.
* To use Sundials with Cantera on a Linux/Unix system, it must be compiled

View file

@ -189,7 +189,7 @@ you can skip any steps which have already been completed.
brew tap homebrew/science
brew update
brew install python scons sundials
brew install python scons
- Verify that your path is set up to use Homebrew's version of Python by
running::

View file

@ -149,21 +149,12 @@ running 'scons build'. The format of this file is:
Command to use for building the Sphinx documentation.
- default: 'sphinx-build'
* use_sundials: [ default | y | n ]
Cantera uses the CVODE or CVODES ODE integrator to time-integrate
reactor network ODE's and for various other purposes. An older
version of CVODE comes with Cantera, but it is possible to use the
latest version as well, which now supports sensitivity analysis
(CVODES). CVODES is a part of the 'sundials' package from Lawrence
Livermore National Laboratory. Sundials is not distributed with
Cantera, but it is free software that may be downloaded and
installed separately. If you leave USE_SUNDIALS = 'default', then it
will be used if you have it, and if not the older CVODE will be
used. Or set USE_SUNDIALS to 'y' or 'n' to force using it or not.
Note that sensitivity analysis with Cantera requires use of
sundials. See: http://www.llnl.gov/CASC/sundials.
* system_sundials: [ default | y | n ]
Select whether to use Sundials from a system installation ('y'),
from a git submodule ('n'), or to decide automatically ('default').
Specifying 'sundials_include' or 'sundials_libdir' changes the
default to 'y'.
- default: 'default'
- actual: 'y'
* sundials_include: [ /path/to/sundials_include ]
The directory where the Sundials header files are installed. This
@ -178,16 +169,6 @@ running 'scons build'. The format of this file is:
/usr/lib.
- default: ''
* sundials_license: [ /path/to/sundials_license ]
Path to the sundials LICENSE file. Needed so that it can be included
when bundling Sundials.
- default: ''
* install_sundials: [ yes | no ]
Determines whether Sundials library and header files are installed
alongside Cantera. Intended for use when installing on Windows.
- default: 'yes'
* blas_lapack_libs: [ string ]
Cantera comes with Fortran (or C) versions of those parts of BLAS
and LAPACK it requires. But performance may be better if you use a

View file

@ -34,12 +34,6 @@ def prep_f2c(env):
return localenv
def prep_sundials(env):
localenv = prep_default(env)
localenv.Prepend(CPPPATH=Dir('#ext/cvode/include'))
return localenv
def prep_gtest(env):
localenv = prep_default(env)
localenv.Prepend(CPPPATH=[Dir('#ext/googletest'),
@ -85,14 +79,38 @@ else:
libs.append(('blas', ['f'], prep_default))
libs.append(('lapack', ['f'], prep_default))
if env['use_sundials'] == 'n':
libs.append(('cvode/source', ['c'], prep_sundials))
for subdir, extensions, prepFunction in libs:
localenv = prepFunction(env)
objects = localenv.SharedObject(mglob(localenv, subdir, *extensions))
libraryTargets.extend(objects)
if env['system_sundials'] == 'n':
localenv = prep_default(env)
localenv.Prepend(CPPPATH=Dir('#include/cantera/ext'))
# Generate sundials_config.h
sundials_configh = {}
if env['OS'] != 'Windows':
sundials_configh['SUNDIALS_USE_GENERIC_MATH'] = 1
if not env['BUILD_BLAS_LAPACK']:
sundials_configh['SUNDIALS_BLAS_LAPACK'] = 1
localenv.AlwaysBuild(env.Command('#include/cantera/ext/sundials/sundials_config.h',
'sundials_config.h.in',
ConfigBuilder(sundials_configh)))
# Copy sundials header files into common include directory
for subdir in ('sundials', 'nvector', 'cvodes', 'ida'):
for header in mglob(env, 'sundials/include/'+subdir, 'h'):
build(localenv.Command('#include/cantera/ext/%s/%s' % (subdir, header.name),
'#ext/sundials/include/%s/%s' % (subdir, header.name),
Copy('$TARGET', '$SOURCE')))
# Compile Sundials source files
for subdir in ('sundials', 'nvec_ser', 'cvodes', 'ida'):
libraryTargets.extend(localenv.SharedObject(
[f for f in mglob(localenv, 'sundials/src/'+subdir, 'c')
if '_klu' not in f.name and '_superlumt' not in f.name]))
# Google Test: Used internally for Cantera unit tests.
if not env['system_googletest']:
localenv = prep_gtest(env)

7
ext/sundials_config.h.in Normal file
View file

@ -0,0 +1,7 @@
/* Minimal set of SUNDIALS configuration variables */
#define SUNDIALS_PACKAGE_VERSION 2.6.2
#define SUNDIALS_F77_FUNC(name,NAME) name ## _
#define SUNDIALS_DOUBLE_PRECISION 1
%(SUNDIALS_USE_GENERIC_MATH)s
%(SUNDIALS_BLAS_LAPACK)s
#define SUNDIALS_EXPORT

View file

@ -33,7 +33,6 @@ typedef int ftnlen; // Fortran hidden string length type
%(FTN_TRAILING_UNDERSCORE)s
%(HAS_SUNDIALS)s
%(SUNDIALS_VERSION)s
//-------- LAPACK / BLAS ---------

View file

@ -9,8 +9,6 @@
#include "cantera/numerics/Integrator.h"
#include "cantera/base/ctexceptions.h"
#ifdef HAS_SUNDIALS
#include "sundials/sundials_nvector.h"
namespace Cantera
@ -30,7 +28,7 @@ public:
/**
* Wrapper class for 'cvodes' integrator from LLNL.
*
* @see FuncEval.h. Classes that use CVodeInt:
* @see FuncEval.h. Classes that use CVodesIntegrator:
* ImplicitChem, ImplicitSurfChem, Reactor
*/
class CVodesIntegrator : public Integrator
@ -120,10 +118,4 @@ private:
} // namespace
#else
#error No sundials!
#endif
#endif

View file

@ -10,8 +10,6 @@
#include "DAE_Solver.h"
#if HAS_SUNDIALS
#include "sundials/sundials_nvector.h"
// These constants are defined internally in the IDA package, ida.c
@ -305,4 +303,3 @@ protected:
}
#endif
#endif

View file

@ -783,11 +783,6 @@ class TestConstPressureReactor(utilities.CanteraTest):
self.integrate()
def test_with_surface_reactions(self):
if (not ct.__sundials_version__ and
self.reactorClass == ct.ConstPressureReactor):
raise unittest.SkipTest("Disabled until there is an interface for "
"setting the max_err_test_fails parameter for the old CVODE")
self.create_reactors(add_surf=True)
self.net1.atol = self.net2.atol = 1e-18
self.net1.rtol = self.net2.rtol = 1e-9
@ -817,9 +812,6 @@ class TestFlowReactor(utilities.CanteraTest):
self.assertNear(v0, r.speed)
self.assertNear(r.distance, v0 * t)
@unittest.skipUnless(ct.__sundials_version__,
"Disabled until there is an interface for setting the "
"max_err_test_fails parameter for the old CVODE")
def test_reacting(self):
g = ct.Solution('gri30.xml')
g.TPX = 1400, 20*101325, 'CO:1.0, H2O:1.0'
@ -946,8 +938,6 @@ class TestWallKinetics(utilities.CanteraTest):
self.assertFalse(bool(bad), bad)
@unittest.skipUnless(ct.__sundials_version__,
"Sensitivity calculations require Sundials")
class TestReactorSensitivities(utilities.CanteraTest):
def test_sensitivities1(self):
net = ct.ReactorNet()

View file

@ -26,10 +26,7 @@ def add_directory(directory):
""" Add a directory to search for Cantera data files. """
CxxAddDirectory(stringify(directory))
if get_sundials_version():
__sundials_version__ = '.'.join(str(get_sundials_version()))
else:
__sundials_version__ = None
__sundials_version__ = '.'.join(str(get_sundials_version()))
__version__ = pystr(get_cantera_version())

View file

@ -42,11 +42,7 @@ pc_incdirs.extend(localenv['extra_inc_dirs'])
localenv['mak_extra_libdirs'] = ' '.join('-L%s' % s for s in localenv['extra_lib_dirs'])
pc_libdirs.extend(localenv['extra_lib_dirs'])
if env['use_sundials'] == 'n':
localenv['mak_sundials_libs'] = '-lcvode'
localenv['mak_sundials_libdir'] = ''
localenv['mak_sundials_include'] = ''
else:
if localenv['system_sundials']:
# Add links to the sundials environment
localenv['mak_sundials_libs'] = ' '.join('-l%s' % s
for s in localenv['sundials_libs'])

View file

@ -14,20 +14,12 @@ def equilSetup(env, subdir, extensions):
env.Append(CPPPATH=['#ext/f2c_libs'])
return defaultSetup(env, subdir, extensions)
def numericsSetup(env, subdir, extensions):
if env['use_sundials'] == 'y':
remove = 'CVodeInt.cpp'
else:
remove = 'CVodesIntegrator.cpp'
return [s for s in mglob(env, subdir, *extensions)
if s.name != remove]
# (subdir, (file extensions), (extra setup(env)))
libs = [('base', ['cpp'], baseSetup),
('thermo', ['cpp'], defaultSetup),
('tpx', ['cpp'], defaultSetup),
('equil', ['cpp','c'], equilSetup),
('numerics', ['cpp'], numericsSetup),
('numerics', ['cpp'], defaultSetup),
('kinetics', ['cpp'], defaultSetup),
('transport', ['cpp'], defaultSetup),
('oneD', ['cpp'], defaultSetup),
@ -37,7 +29,7 @@ libs = [('base', ['cpp'], baseSetup),
for subdir, extensions, setup in libs:
localenv = env.Clone()
localenv.Prepend(CPPPATH=Dir('#include'))
localenv.Prepend(CPPPATH=[Dir('#include'), Dir('#include/cantera/ext')])
localenv.Append(CCFLAGS=env['warning_flags'])
source = setup(localenv, subdir, extensions)
objects = localenv.SharedObject(source)
@ -56,7 +48,7 @@ env['cantera_staticlib'] = lib
# Windows and OS X require shared libraries at link time
if localenv['OS'] in ('Darwin', 'Windows', 'Cygwin'):
localenv.Append(LIBS=localenv['FORTRANSYSLIBS'])
if (localenv['use_sundials'] == 'y'):
if (localenv['system_sundials'] == 'y'):
localenv.Append(LIBS=localenv['sundials_libs'],
LIBPATH=localenv['sundials_libdir'])
if localenv['blas_lapack_libs']:

View file

@ -1,315 +0,0 @@
/**
* @file CVodeInt.cpp
*/
// Copyright 2001 California Institute of Technology
#include "CVodeInt.h"
using namespace std;
// CVODE includes
#include "../../ext/cvode/include/llnltyps.h"
#include "../../ext/cvode/include/llnlmath.h"
#include "../../ext/cvode/include/cvode.h"
#include "../../ext/cvode/include/cvdense.h"
#include "../../ext/cvode/include/cvdiag.h"
#include "../../ext/cvode/include/cvspgmr.h"
#include "../../ext/cvode/include/cvode.h"
#include "cantera/base/stringUtils.h"
extern "C" {
/**
* Function called by CVODE 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 void cvode_rhs(integer N, real t, N_Vector y, N_Vector ydot,
void* f_data)
{
double* ydata = N_VDATA(y);
double* ydotdata = N_VDATA(ydot);
Cantera::FuncEval* f = (Cantera::FuncEval*)f_data;
f->eval(t, ydata, ydotdata, NULL);
}
/**
* Function called by CVODE to evaluate the Jacobian matrix.
* (temporary)
* @ingroup odeGroup
*/
static void cvode_jac(integer N, DenseMat J, RhsFn f, void* f_data,
real t, N_Vector y, N_Vector fy, N_Vector ewt, real h, real uround,
void* jac_data, long int* nfePtr, N_Vector vtemp1, N_Vector vtemp2,
N_Vector vtemp3)
{
// get pointers to start of data
double* ydata = N_VDATA(y);
double* fydata = N_VDATA(fy);
double* ewtdata = N_VDATA(ewt);
double* ydot = N_VDATA(vtemp1);
Cantera::FuncEval* func = (Cantera::FuncEval*)f_data;
int i,j;
double* col_j;
double ysave, dy;
for (j=0; j < N; j++) {
col_j = (J->data)[j];
ysave = ydata[j];
dy = 1.0/ewtdata[j];
ydata[j] = ysave + dy;
dy = ydata[j] - ysave;
func->eval(t, ydata, ydot, NULL);
for (i=0; i < N; i++) {
col_j[i] = (ydot[i] - fydata[i])/dy;
}
ydata[j] = ysave;
}
}
}
namespace Cantera
{
CVodeInt::CVodeInt() : m_neq(0),
m_cvode_mem(0),
m_t0(0.0),
m_y(0),
m_abstol(0),
m_type(DENSE+NOJAC),
m_itol(0),
m_method(BDF),
m_iter(NEWTON),
m_maxord(0),
m_reltol(1.e-9),
m_abstols(1.e-15),
m_nabs(0),
m_hmax(0.0),
m_maxsteps(20000)
{
m_ropt.resize(OPT_SIZE,0.0);
m_iopt = new long[OPT_SIZE];
fill(m_iopt, m_iopt+OPT_SIZE,0);
}
CVodeInt::~CVodeInt()
{
if (m_cvode_mem) {
CVodeFree(m_cvode_mem);
}
if (m_y) {
N_VFree(m_y);
}
if (m_abstol) {
N_VFree(m_abstol);
}
delete[] m_iopt;
}
double& CVodeInt::solution(size_t k)
{
return N_VIth(m_y, int(k));
}
double* CVodeInt::solution()
{
return N_VDATA(m_y);
}
void CVodeInt::setTolerances(double reltol, size_t n, double* abstol)
{
m_itol = 1;
m_nabs = int(n);
if (m_nabs != m_neq) {
if (m_abstol) {
N_VFree(m_abstol);
}
m_abstol = N_VNew(m_nabs, 0);
}
for (int i=0; i<m_nabs; i++) {
N_VIth(m_abstol, i) = abstol[i];
}
m_reltol = reltol;
}
void CVodeInt::setTolerances(double reltol, double abstol)
{
m_itol = 0;
m_reltol = reltol;
m_abstols = abstol;
}
void CVodeInt::setProblemType(int probtype)
{
m_type = probtype;
}
void CVodeInt::setMethod(MethodType t)
{
if (t == BDF_Method) {
m_method = BDF;
} else if (t == Adams_Method) {
m_method = ADAMS;
} else {
throw CVodeErr("unknown method");
}
}
void CVodeInt::setMaxStepSize(doublereal hmax)
{
m_hmax = hmax;
m_ropt[HMAX] = hmax;
}
void CVodeInt::setMinStepSize(doublereal hmin)
{
m_hmin = hmin;
m_ropt[HMIN] = hmin;
}
void CVodeInt::setMaxSteps(int nmax)
{
m_maxsteps = nmax;
m_iopt[MXSTEP] = m_maxsteps;
}
void CVodeInt::setIterator(IterType t)
{
if (t == Newton_Iter) {
m_iter = NEWTON;
} else if (t == Functional_Iter) {
m_iter = FUNCTIONAL;
} else {
throw CVodeErr("unknown iterator");
}
}
void CVodeInt::initialize(double t0, FuncEval& func)
{
m_neq = int(func.neq());
m_t0 = t0;
if (m_y) {
N_VFree(m_y); // free solution vector if already allocated
}
m_y = N_VNew(m_neq, 0); // allocate solution vector
// check abs tolerance array size
if (m_itol == 1 && m_nabs < m_neq) {
throw CVodeErr("not enough absolute tolerance values specified.");
}
func.getState(N_VDATA(m_y));
// set options
m_iopt[MXSTEP] = m_maxsteps;
m_iopt[MAXORD] = m_maxord;
m_ropt[HMAX] = m_hmax;
if (m_cvode_mem) {
CVodeFree(m_cvode_mem);
}
// pass a pointer to func in m_data
m_data = (void*)&func;
if (m_itol) {
m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, m_y, m_method,
m_iter, m_itol, &m_reltol,
m_abstol, m_data, NULL, 1, m_iopt,
m_ropt.data(), NULL);
} else {
m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, m_y, m_method,
m_iter, m_itol, &m_reltol,
&m_abstols, m_data, NULL, 1, m_iopt,
m_ropt.data(), NULL);
}
if (!m_cvode_mem) {
throw CVodeErr("CVodeMalloc failed.");
}
if (m_type == DENSE + NOJAC) {
CVDense(m_cvode_mem, NULL, NULL);
} else if (m_type == DENSE + JAC) {
CVDense(m_cvode_mem, cvode_jac, NULL);
} else if (m_type == DIAG) {
CVDiag(m_cvode_mem);
} else if (m_type == GMRES) {
CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0,
NULL, NULL, NULL);
} else {
throw CVodeErr("unsupported option");
}
}
void CVodeInt::reinitialize(double t0, FuncEval& func)
{
m_t0 = t0;
func.getState(N_VDATA(m_y));
// set options
m_iopt[MXSTEP] = m_maxsteps;
m_iopt[MAXORD] = m_maxord;
m_ropt[HMAX] = m_hmax;
// pass a pointer to func in m_data
m_data = (void*)&func;
int result;
if (m_itol) {
result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, m_y, m_method,
m_iter, m_itol, &m_reltol,
m_abstol, m_data, NULL, 1, m_iopt,
m_ropt.data(), NULL);
} else {
result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, m_y, m_method,
m_iter, m_itol, &m_reltol,
&m_abstols, m_data, NULL, 1, m_iopt,
m_ropt.data(), NULL);
}
if (result != 0) {
throw CVodeErr("CVReInit failed.");
}
if (m_type == DENSE + NOJAC) {
CVDense(m_cvode_mem, NULL, NULL);
} else if (m_type == DENSE + JAC) {
CVDense(m_cvode_mem, cvode_jac, NULL);
} else if (m_type == DIAG) {
CVDiag(m_cvode_mem);
} else if (m_type == GMRES) {
CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0,
NULL, NULL, NULL);
} else {
throw CVodeErr("unsupported option");
}
}
void CVodeInt::integrate(double tout)
{
double t;
int flag;
flag = CVode(m_cvode_mem, tout, m_y, &t, NORMAL);
if (flag != SUCCESS) {
throw CVodeErr(" CVode error encountered. Error code: " + int2str(flag));
}
}
double CVodeInt::step(double tout)
{
double t;
int flag;
flag = CVode(m_cvode_mem, tout, m_y, &t, ONE_STEP);
if (flag != SUCCESS) {
throw CVodeErr(" CVode error encountered. Error code: " + int2str(flag));
}
return t;
}
int CVodeInt::nEvals() const
{
return m_iopt[NFE];
}
}

View file

@ -1,88 +0,0 @@
/**
* @file CVodeInt.h
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_CVODEINT_H
#define CT_CVODEINT_H
#include "cantera/numerics/Integrator.h"
#include "cantera/numerics/FuncEval.h"
#include "cantera/base/ctexceptions.h"
#include "cantera/base/ct_defs.h"
#include "../../ext/cvode/include/nvector.h"
namespace Cantera
{
/**
* Exception thrown when a CVODE error is encountered.
*/
class CVodeErr : public CanteraError
{
public:
explicit CVodeErr(const std::string& msg) : CanteraError("CVodeInt", msg) {}
};
/**
* Wrapper class for 'CVODE' integrator from LLNL.
* The unmodified CVODE code is in directory ext/cvode.
*
* @see FuncEval.h. Classes that use CVodeInt:
* ImplicitChem, ImplicitSurfChem, Reactor
*/
class CVodeInt : public Integrator
{
public:
/*!
* Constructor. Default settings: dense Jacobian, no user-supplied
* Jacobian function, Newton iteration.
*/
CVodeInt();
virtual ~CVodeInt();
virtual void setTolerances(double reltol, size_t n, double* abstol);
virtual void setTolerances(double reltol, double abstol);
virtual void setProblemType(int probtype);
virtual void initialize(double t0, FuncEval& func);
virtual void reinitialize(double t0, FuncEval& func);
virtual void integrate(double tout);
virtual doublereal step(double tout);
virtual double& solution(size_t k);
virtual double* solution();
virtual int nEquations() const {
return m_neq;
}
virtual int nEvals() const;
virtual void setMaxOrder(int n) {
m_maxord = n;
}
virtual void setMethod(MethodType t);
virtual void setIterator(IterType t);
virtual void setMaxStepSize(double hmax);
virtual void setMinStepSize(double hmin);
virtual void setMaxSteps(int nmax);
virtual void setMaxErrTestFails(int nmax) {}
private:
int m_neq;
void* m_cvode_mem;
double m_t0;
N_Vector m_y, m_abstol;
int m_type;
int m_itol;
int m_method;
int m_iter;
int m_maxord;
double m_reltol;
double m_abstols;
int m_nabs;
double m_hmax, m_hmin;
int m_maxsteps;
vector_fp m_ropt;
long int* m_iopt;
void* m_data;
};
} // namespace
#endif // CT_CVODE

View file

@ -20,12 +20,7 @@ namespace Cantera
DAE_Solver* newDAE_Solver(const std::string& itype, ResidJacEval& f)
{
if (itype == "IDA") {
#ifdef HAS_SUNDIALS
return new IDA_Solver(f);
#else
throw CanteraError("newDAE_Solver","IDA solver requires sundials"
" package, but Cantera was not built with sundials.");
#endif
} else {
throw CanteraError("newDAE_Solver",
"unknown DAE solver: "+itype);

View file

@ -5,7 +5,6 @@
#include "cantera/numerics/IDA_Solver.h"
#include "cantera/base/stringUtils.h"
#if HAS_SUNDIALS
#include "sundials/sundials_types.h"
#include "sundials/sundials_math.h"
#include "ida/ida.h"
@ -583,4 +582,3 @@ doublereal IDA_Solver::getOutputParameter(int flag) const
}
}
#endif

View file

@ -1,12 +1,7 @@
//! @file ODE_integrators.cpp
#include "cantera/base/ct_defs.h"
#include "cantera/numerics/Integrator.h"
#ifdef HAS_SUNDIALS
#include "cantera/numerics/CVodesIntegrator.h"
#else
#include "CVodeInt.h"
#endif
namespace Cantera
{
@ -14,11 +9,7 @@ namespace Cantera
Integrator* newIntegrator(const std::string& itype)
{
if (itype == "CVODE") {
#ifdef HAS_SUNDIALS
return new CVodesIntegrator();
#else
return new CVodeInt();
#endif
} else {
throw CanteraError("newIntegrator",
"unknown ODE integrator: "+itype);