Skip to content

Commit ec9e209

Browse files
authored
Fixes regression caused by #387 (#389)
* The default values changed in the commit (ba1065c) breaks example such as https://github.com/BhallaLab/moose-examples/blob/09ca09e68f163a0920653a9400214aff10b6ba16/snippets/rxdFuncDiffusion.py . The sparse matrix has upper limit of number of rows and columns to 20,000. In the example linked, new values makes it impossible to run the example as is. To overcome this, we notify the user whenever this limit is reached and ask them to set `diffLength` before setting up the `x1`. On top of this, we can also revert default values to original larger values. Not sure why these values were changed to the scale of 1e-6? Unless the reason is known, I am not going to change current values. The above linked example now works with this commit. * Script which switches solver is now working fine. Forgot to uncomment `unzombifyModel` in `~Stoich` in previous PR #387. * switch solver script is working fine now. Added to the test suite. * During zombiefication, deepcopy of parser is expected. Added more tests and fixed the deepcopy of parser issue. In Zombiefication, the parser was not deep copied resulting in erronous values in couple of tests. There is some memory leak now. * Prepare a PR now. Test on travis. Some tests might fail with BOOST. Memory leak is still there. * 1. Removed copy constructor from moose::Function. It was not used anywhere. Increased rtol value for a test. Multithreaded solvers gives different results. 2. Fixed all memory leaks. Probably I don't understand how EXPRTK really works. using smart pointers with EXPRTK caused memory leak. 3. Log memory leak on travis using valgrind. Install valgrind in docker images as well. * During zombiefication, deepcopy of parser is expected. Added fix and a test case. * Added more tests and fixed the deepcopy of parser issue. In Zombiefication, the parser was not deep coped resulting in erronous values in couple of tets. There is some memory leak now (not very large, 8 bytes per variable per expression). * Prepare a PR now. Test on travis. Some tests might fail with BOOST. Memory leak is still there. * removed copy constructor; it was not used anywhere. [skip ci] Increased rtol value for a test. Multithreaded solvers gives different results. * Fixed all memory leaks. Probably I don't understand how EXPRTK really works. using smart pointers with EXPRTK caused memory leak. Log memory leak on travis using valgrind. Fixed tests. Let the EXPRK object manage its memory. * BOOST/GSL are only needed in ksolve directory: tweaked cmake to change compilation flags on ksolve directory only. Build will be faster for various configurations. Moved one test to fixme (Vinu's model). * Updated gitlab pipeline. On a single threaded virtual machine, numThreads was set to 0 in couple of tests. Fixed that. Install pyneuroml to the pipeline. Small leeway in a test. * std can be close to zero. np.allclose may not handle it properly all the time. * boost solver with GSSA may have large variation. * boost solver with GSSA may have large variation. Test for the sum of all errors. * Increased the tolerance a bit more.
1 parent d3fe5e9 commit ec9e209

28 files changed

+370
-190
lines changed

.ci/travis_build_linux.sh

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
set -e
1010
set -x
1111

12+
BUILDDIR=_build_travis
13+
mkdir -p $BUILDDIR
14+
1215
PYTHON2="/usr/bin/python2"
1316
PYTHON3="/usr/bin/python3"
1417

@@ -32,32 +35,36 @@ $PYTHON3 -m compileall -q .
3235

3336
# Python3 with GSL in debug more.
3437
(
35-
mkdir -p _GSL_BUILD_PY3 && cd _GSL_BUILD_PY3 && \
38+
mkdir -p $BUILDDIR && cd $BUILDDIR && \
3639
cmake -DPYTHON_EXECUTABLE=$PYTHON3 \
3740
-DCMAKE_INSTALL_PREFIX=/usr -DDEBUG=ON ..
38-
# Don't run test_long prefix. They take very long time in DEBUG mode.
39-
$MAKE && MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure -E ".*test_long*"
41+
$MAKE
42+
# Run with valgrind to log any memory leak.
43+
valgrind --leak-check=full ./moose.bin -q -u
44+
45+
# Run all tests in debug mode.
46+
MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure
4047
make install || sudo make install
4148
cd /tmp
4249
$PYTHON3 -c 'import moose;print(moose.__file__);print(moose.version())'
4350
)
4451

45-
# BOOST and python3
46-
(
47-
mkdir -p _BOOST_BUILD_PY3 && cd _BOOST_BUILD_PY3 && \
48-
cmake -DWITH_BOOST_ODE=ON -DPYTHON_EXECUTABLE="$PYTHON3" \
49-
-DCMAKE_INSTALL_PREFIX=/usr ..
50-
$MAKE && MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure
51-
)
52-
5352
# GSL and python2, failure is allowed
5453
set +e
5554
(
56-
BUILDDIR=_GSL_PY2
5755
mkdir -p $BUILDDIR && cd $BUILDDIR && \
5856
cmake -DPYTHON_EXECUTABLE=$PYTHON2 -DCMAKE_INSTALL_PREFIX=/usr ..
5957
$MAKE && MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure
6058
)
6159
set -e
6260

61+
62+
# BOOST and python3
63+
(
64+
mkdir -p $BUILDDIR && cd $BUILDDIR && \
65+
cmake -DWITH_BOOST_ODE=ON -DPYTHON_EXECUTABLE="$PYTHON3" \
66+
-DCMAKE_INSTALL_PREFIX=/usr ..
67+
$MAKE && MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure
68+
)
69+
6370
echo "All done"

.ci/travis_build_osx.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
set -o nounset # Treat unset variables as an error
2121
set -e
2222

23+
BUILDDIR=_build_travis
24+
2325
NPROC=$(nproc)
2426
(
2527
# Make sure not to pick up python from /opt.
@@ -32,14 +34,14 @@ NPROC=$(nproc)
3234
$PYTHON3 -m pip install python-libsbml --user
3335
$PYTHON3 -m pip install pyneuroml --user
3436

35-
mkdir -p _GSL_BUILD && cd _GSL_BUILD \
37+
mkdir -p $BUILDDIR && cd $BUILDDIR \
3638
&& cmake -DPYTHON_EXECUTABLE=$PYTHON3 \
3739
..
3840
make pylint -j$NPROC
3941
make -j$NPROC && MOOSE_NUM_THREAD=$NPROC ctest --output-on-failure -j$NPROC
4042

4143
cd .. # Now with boost.
42-
mkdir -p _BOOST_BUILD && cd _BOOST_BUILD \
44+
mkdir -p $BUILDDIR && cd $BUILDDIR \
4345
&& cmake -DWITH_BOOST_ODE=ON \
4446
-DPYTHON_EXECUTABLE=`which python3` ..
4547

.ci/travis_prepare_linux.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ apt-get install -qq make cmake
1313
apt-get install -qq python-numpy python-matplotlib python-networkx python-pip
1414
apt-get install -qq python3-numpy python3-matplotlib python3-networkx python3-pip
1515
apt-get install -qq python-tk python3-tk
16+
apt-get install -qq valgrind
1617

1718
# Gsl
1819
apt-get install -qq libgsl0-dev || apt-get install -qq libgsl-dev

.gitlab-ci.yml

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,8 @@ build:
1313
- apt -y install python3-numpy python3-matplotlib python3-pip python3-dev
1414
- apt -y install python-numpy python-matplotlib python-pip python-dev
1515
script:
16-
- python3 setup.py install
1716
- python3 -m pip install setuptools pip --user --upgrade
18-
- python2 setup.py install
19-
- python2 -m pip install setuptools pip --user --upgrade
20-
- python3 setup.py sdist
21-
artifacts:
22-
paths:
23-
- mybinary
24-
# depending on your build setup it's most likely a good idea to cache outputs to reduce the build time
25-
# cache:
26-
# paths:
27-
# - "*.o"
28-
29-
# run tests using the binary built before
30-
test:
31-
stage: test
32-
script:
33-
- python3 setup.py test
17+
- python3 -m pip install pyneuroml --user --upgrade
18+
- python3 setup.py build test
19+
- python3 setup.py install --user
20+
- python3 -c "import moose; moose.test()"

CMakeLists.txt

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,7 @@ elseif(ENABLE_UNIT_TESTS)
8484
else()
8585
message(STATUS "Building for Release/No unit tests.")
8686
set(CMAKE_BUILD_TYPE Release)
87-
add_definitions(-UDO_UNIT_TESTS -O3 -DDISABLE_DEBUG)
88-
89-
# DO NOT Treat all warnings as errors. With some compilers and newer versions
90-
# this often causes headache.
91-
# add_definitions(-Werror)
87+
add_definitions(-UDO_UNIT_TESTS -O3 -DDISABLE_DEBUG)
9288
endif()
9389

9490
if(GPROF AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
@@ -160,20 +156,11 @@ if(WITH_GSL)
160156
"====================================================================\n"
161157
)
162158
endif(NOT GSL_FOUND)
163-
add_definitions(-DUSE_GSL)
164-
# GSL is also used in RNG (whenever applicable), therefore include paths are
165-
# top level.
166-
include_directories( ${GSL_INCLUDE_DIRS} )
167159
elseif(WITH_BOOST_ODE)
168160
find_package(Boost 1.53 REQUIRED)
169161
find_package(LAPACK REQUIRED)
170162
endif()
171163

172-
# if boost ode is being used, don't use GSL.
173-
if(WITH_BOOST_ODE)
174-
add_definitions(-DUSE_BOOST_ODE -UUSE_GSL)
175-
include_directories(${Boost_INCLUDE_DIRS})
176-
endif()
177164

178165
# Openmpi
179166
if(WITH_MPI)

builtins/Function.cpp

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -318,24 +318,8 @@ Function::Function():
318318
{
319319
}
320320

321-
Function::Function(const Function& f) :
322-
valid_(f.valid_),
323-
numVar_(f.numVar_),
324-
lastValue_(f.lastValue_),
325-
rate_(f.rate_),
326-
mode_(f.mode_),
327-
useTrigger_(f.useTrigger_),
328-
doEvalAtReinit_(f.doEvalAtReinit_),
329-
t_(f.t_),
330-
independent_(f.independent_),
331-
xs_(f.xs_),
332-
ys_(f.ys_),
333-
stoich_(f.stoich_)
334-
{
335-
parser_.LinkVariables(xs_, ys_, &t_);
336-
}
337-
338-
// Careful: This is a critical function.
321+
// Careful: This is a critical function. Also since during zombiefication, deep
322+
// copy is expected. Merely copying the parser won't work.
339323
Function& Function::operator=(const Function& rhs)
340324
{
341325
// protect from self-assignment.
@@ -351,9 +335,23 @@ Function& Function::operator=(const Function& rhs)
351335
t_ = rhs.t_;
352336
rate_ = rhs.rate_;
353337
independent_ = rhs.independent_;
354-
xs_ = rhs.xs_;
355-
ys_ = rhs.ys_;
356-
parser_.LinkVariables(xs_, ys_, &t_);
338+
339+
// Deep copy; create new Variable and constant to link with new parser.
340+
// Zombification requires it. DO NOT just copy the object/pointer of
341+
// MooseParser.
342+
xs_.clear();
343+
ys_.clear();
344+
parser_.ClearAll();
345+
if(rhs.parser_.GetExpr().size() > 0)
346+
{
347+
for(auto x: rhs.xs_)
348+
xs_.push_back(shared_ptr<Variable>(new Variable()));
349+
for(auto y: rhs.ys_)
350+
ys_.push_back(shared_ptr<double>(new double(0.0)));
351+
352+
parser_.LinkVariables(xs_, ys_, &t_);
353+
parser_.SetExpr(rhs.parser_.GetExpr());
354+
}
357355
return *this;
358356
}
359357

@@ -395,7 +393,7 @@ void Function::addVariable(const string& name)
395393
{
396394
// Equality with index because we cound from 0.
397395
for (size_t i = xs_.size(); i <= (size_t) index; i++)
398-
xs_.push_back(new Variable());
396+
xs_.push_back(shared_ptr<Variable>(new Variable()));
399397
}
400398

401399
// This must be true.
@@ -414,9 +412,9 @@ void Function::addVariable(const string& name)
414412
{
415413
// Equality with index because we cound from 0.
416414
for (size_t i = ys_.size(); i <= (size_t) index; i++)
417-
ys_.push_back(new double(0.0));
415+
ys_.push_back(shared_ptr<double>(new double(0.0)));
418416
}
419-
parser_.DefineVar(name, ys_[index]);
417+
parser_.DefineVar(name, ys_[index].get());
420418
}
421419
else if (name == "t")
422420
parser_.DefineVar("t", &t_);
@@ -601,7 +599,7 @@ Variable * Function::getVar(unsigned int ii)
601599
{
602600
static Variable dummy;
603601
if ( ii < xs_.size())
604-
return xs_[ii];
602+
return xs_[ii].get();
605603

606604
MOOSE_WARN( "Warning: Function::getVar: index: "
607605
<< ii << " is out of range: "

builtins/Function.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class Function
2424
public:
2525
static const int VARMAX;
2626
Function();
27-
Function(const Function& f);
2827

2928
// Destructor.
3029
~Function();
@@ -106,17 +105,15 @@ class Function
106105

107106
// this stores variables received via incoming messages, identifiers of
108107
// the form x{i} are included in this
109-
vector<Variable*> xs_;
108+
vector<shared_ptr<Variable>> xs_;
110109

111110
// this stores variable values pulled by sending request. identifiers of
112111
// the form y{i} are included in this
113-
vector<double*> ys_;
112+
vector<shared_ptr<double>> ys_;
114113

115114
// Used by kinetic solvers when this is zombified.
116115
void* stoich_;
117116

118-
// Parser which should never be copied. Multithreaded programs may behave
119-
// strangely if copy-constructor or operator()= is implemented.
120117
moose::MooseParser parser_;
121118

122119
};

builtins/MooseParser.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ using namespace std;
2323
namespace moose
2424
{
2525

26-
MooseParser::MooseParser() :
27-
expression_(new moose::Parser::expression_t())
28-
, symbol_tables_registered_(false)
26+
MooseParser::MooseParser()
2927
{
3028
Parser::symbol_table_t symbol_table;
3129

@@ -39,8 +37,7 @@ MooseParser::MooseParser() :
3937
symbol_table.add_function( "srand2", MooseParser::SRand2 );
4038
symbol_table.add_function( "fmod", MooseParser::Fmod );
4139

42-
expression_->register_symbol_table(symbol_table);
43-
40+
expression_.register_symbol_table(symbol_table);
4441
}
4542

4643
MooseParser::~MooseParser()
@@ -88,9 +85,14 @@ double MooseParser::Fmod( double a, double b )
8885
/*-----------------------------------------------------------------------------
8986
* Get/Set
9087
*-----------------------------------------------------------------------------*/
91-
Parser::symbol_table_t& MooseParser::GetSymbolTable( ) const
88+
Parser::symbol_table_t& MooseParser::GetSymbolTable()
9289
{
93-
return expression_->get_symbol_table();
90+
return expression_.get_symbol_table();
91+
}
92+
93+
const Parser::symbol_table_t& MooseParser::GetSymbolTable() const
94+
{
95+
return expression_.get_symbol_table();
9496
}
9597

9698
double MooseParser::GetVarValue(const string& name) const
@@ -210,7 +212,7 @@ bool MooseParser::CompileExpr()
210212
ASSERT_FALSE(expr_.empty(), __func__ << ": Empty expression not allowed here");
211213

212214
Parser::parser_t parser;
213-
auto res = parser.compile(expr_, *expression_);
215+
auto res = parser.compile(expr_, expression_);
214216
if(! res)
215217
{
216218
std::stringstream ss;
@@ -239,14 +241,14 @@ bool MooseParser::CompileExpr()
239241

240242
double MooseParser::Derivative(const string& name) const
241243
{
242-
return exprtk::derivative(*expression_, name);
244+
return exprtk::derivative(expression_, name);
243245
}
244246

245247
double MooseParser::Eval(bool check) const
246248
{
247249
if( expr_.empty())
248250
return 0.0;
249-
double v = expression_->value();
251+
double v = expression_.value();
250252
if(check)
251253
{
252254
if(! std::isfinite(v))
@@ -278,14 +280,19 @@ Parser::varmap_type MooseParser::GetConst( ) const
278280

279281
void MooseParser::ClearVariables( )
280282
{
281-
GetSymbolTable().clear_variables(false);
283+
GetSymbolTable().clear_variables();
282284
}
283285

284286
void MooseParser::ClearAll( )
285287
{
286288
ClearVariables();
287289
}
288290

291+
void MooseParser::Reset( )
292+
{
293+
expression_.release();
294+
}
295+
289296
const string MooseParser::GetExpr( ) const
290297
{
291298
return expr_;
@@ -302,5 +309,17 @@ void MooseParser::LinkVariables(vector<Variable*>& xs, vector<double*>& ys, doub
302309
DefineVar("t", t);
303310
}
304311

312+
void MooseParser::LinkVariables(vector<shared_ptr<Variable>>& xs, vector<shared_ptr<double>>& ys, double* t)
313+
{
314+
for(size_t i = 0; i < xs.size(); i++)
315+
DefineVar('x'+to_string(i), xs[i]->ref());
316+
317+
for (size_t i = 0; i < ys.size(); i++)
318+
DefineVar('y'+to_string(i), ys[i].get());
319+
320+
DefineVar("t", t);
321+
}
322+
323+
305324

306325
} // namespace moose.

0 commit comments

Comments
 (0)