[SCons/Numerics] Use ext/sundials if system Sundials not installed
This commit is contained in:
parent
34e38ab007
commit
b4a1fb2db1
18 changed files with 99 additions and 561 deletions
114
SConstruct
114
SConstruct
|
|
@ -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'))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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::
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
7
ext/sundials_config.h.in
Normal 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
|
||||
|
|
@ -33,7 +33,6 @@ typedef int ftnlen; // Fortran hidden string length type
|
|||
%(FTN_TRAILING_UNDERSCORE)s
|
||||
|
||||
|
||||
%(HAS_SUNDIALS)s
|
||||
%(SUNDIALS_VERSION)s
|
||||
|
||||
//-------- LAPACK / BLAS ---------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
||||
|
|
|
|||
|
|
@ -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'])
|
||||
|
|
|
|||
|
|
@ -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']:
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue