diff --git a/moose-core/.travis/travis_build_linux.sh b/moose-core/.travis/travis_build_linux.sh index 3009af21b0f185f8dbe2760711cc4b5663ec6f5f..a4499d303dc96fd07a21d527e37421d26ee048c7 100755 --- a/moose-core/.travis/travis_build_linux.sh +++ b/moose-core/.travis/travis_build_linux.sh @@ -18,13 +18,13 @@ # REVISION: --- #=============================================================================== -set -e -x +set -e +set -x PYTHON2="/usr/bin/python2" PYTHON3="/usr/bin/python3" MAKEFLAGS="-j`nproc`" - if [ ! -n "$MAKE" ]; then MAKE="make -j`nproc`" else @@ -42,34 +42,34 @@ if type $PYTHON3 > /dev/null; then $PYTHON3 -m compileall -q . ; fi echo "Currently in `pwd`" ( - mkdir -p _GSL_BUILD && cd _GSL_BUILD + mkdir -p _GSL_BUILD && cd _GSL_BUILD cmake -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON2" .. - $MAKE && ctest --output-on-failure - sudo make install + $MAKE && ctest --output-on-failure -j4 + sudo make install && cd /tmp $PYTHON2 -c 'import moose;print(moose.__file__);print(moose.version())' ) ( # Now with boost. mkdir -p _BOOST_BUILD && cd _BOOST_BUILD && \ - cmake -DWITH_BOOST=ON -DDEBUG=ON -DQUIET_MODE=ON -DPYTHON_EXECUTABLE="$PYTHON2" .. - $MAKE && ctest --output-on-failure + cmake -DWITH_BOOST_ODE=ON -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON2" .. + $MAKE && ctest --output-on-failure -j4 ) # This is only applicable on linux build. echo "Python3: Removed python2-networkx and install python3" if type $PYTHON3 > /dev/null; then - sudo apt-get remove -qq python-networkx - sudo apt-get install -qq python3-networkx + sudo apt-get remove -qq python-networkx || echo "Error with apt" + sudo apt-get install -qq python3-networkx || echo "Error with apt" ( mkdir -p _GSL_BUILD2 && cd _GSL_BUILD2 && \ cmake -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON3" .. - $MAKE && ctest --output-on-failure + $MAKE && ctest --output-on-failure -j4 ) ( mkdir -p _BOOST_BUILD2 && cd _BOOST_BUILD2 && \ - cmake -DWITH_BOOST=ON -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON3" .. - $MAKE && ctest --output-on-failure + cmake -DWITH_BOOST_ODE=ON -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON3" .. + $MAKE && ctest --output-on-failure -j4 ) echo "All done" else diff --git a/moose-core/.travis/travis_build_osx.sh b/moose-core/.travis/travis_build_osx.sh index 0b446a202543a7f70409f51397ab44c10a172f7f..814f6af5293a05be09313b8cbf01ed1ca4245dbc 100755 --- a/moose-core/.travis/travis_build_osx.sh +++ b/moose-core/.travis/travis_build_osx.sh @@ -20,21 +20,23 @@ set -o nounset # Treat unset variables as an error set -e +# NOTE: On travis, don't enable -j`nproc` option. It may not compile properly. + ( # Make sure not to pick up python from /opt. PATH=/usr/bin:/usr/local/bin:$PATH mkdir -p _GSL_BUILD && cd _GSL_BUILD \ - && cmake -DQUIET_MODE=ON -DDEBUG=ON \ + && cmake -DDEBUG=ON \ -DPYTHON_EXECUTABLE=`which python` .. - make -j3 && ctest --output-on-failure + make && ctest --output-on-failure cd .. # Now with boost. mkdir -p _BOOST_BUILD && cd _BOOST_BUILD \ - && cmake -DWITH_BOOST=ON -DDEBUG=ON \ + && cmake -DWITH_BOOST_ODE=ON -DDEBUG=ON \ -DPYTHON_EXECUTABLE=`which python` .. - make -j3 && ctest --output-on-failure + make && ctest --output-on-failure cd .. set +e diff --git a/moose-core/AUTHORS b/moose-core/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..565695af709d18d0db50b9bd0e1662ddcd5e30aa --- /dev/null +++ b/moose-core/AUTHORS @@ -0,0 +1,17 @@ +# Active developers + +Upinder S. Bhalla Primary Architect, rdesigneur +HarshaRani. G.V MOOSE Website, SBML support, GUI +Dilawar Singh Multithreading, GSoC, Packaging, Maintenance, BOOST solvers + +# Past developers + +Subhasis Ray Python interface, GUI +Niraj Dudani Neuronal solver +Aditya Gilra NeuroML support +Aviral Goel Moogli + +# Contributors + +Padraid Gleeson NeuroML2 support +Dharma Teja GPU parallelization using CUDA diff --git a/moose-core/AUTHROS b/moose-core/AUTHROS deleted file mode 100644 index f568c742ebe5fc90330f250c3c5e035224fed581..0000000000000000000000000000000000000000 --- a/moose-core/AUTHROS +++ /dev/null @@ -1,9 +0,0 @@ -Upinder S. Bhalla Primary Architect -Niraj Dudani Neuronal solver -Subhasis Ray Python interface -Aditya Gilra NeuroML support -Aviral Goel Moogli -HarshaRani. G.V Designing of Website,read and write SBML and - Graphical User Interface for moose -Dilawar Singh Packaging, BOOST solvers -Dharma Teja GPU parallelization using CUDA diff --git a/moose-core/CMakeLists.txt b/moose-core/CMakeLists.txt index bd6aaf84449898d713efba60273018fa55b0bf0d..59977a0fa04ab1929aba24b7b7d8b56fbeb9f298 100644 --- a/moose-core/CMakeLists.txt +++ b/moose-core/CMakeLists.txt @@ -1,18 +1,6 @@ -set(CMAKE_LEGACY_CYGWIN_WIN32 0) cmake_minimum_required(VERSION 2.8 FATAL_ERROR) - - project(pymoose) -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) - cmake_policy(SET CMP0004 NEW) - if(POLICY CMP0050) - cmake_policy(SET CMP0050 OLD) - endif(POLICY CMP0050) -endif(COMMAND cmake_policy) - - set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules") include(CheckCXXCompiler.cmake) include(CheckIncludeFileCXX) @@ -88,22 +76,24 @@ else() endif() ################################ CMAKE OPTIONS ################################## -option(DEBUG "Build with debug support" OFF) -option(GPROF "Build for profiling using gprof" OFF) -option(ENABLE_UNIT_TESTS "Enable unit tests (DEBUG should also be ON)" OFF) -option(WITH_MPI "Enable Openmpi support" OFF) -option(WITH_BOOST "Use boost library instead of GSL" OFF) -option(WITH_GSL "Use gsl-library. Alternative is WITH_BOOST" ON) +option(DEBUG "Build with debug support" OFF) +option(GPROF "Build for profiling using gprof" OFF) +option(ENABLE_UNIT_TESTS "Enable unit tests (DEBUG should also be ON)" OFF) +option(WITH_MPI "Enable Openmpi support" OFF) +option(WITH_BOOST_ODE "Use boost library ode2 library instead of GSL" OFF) +option(WITH_GSL "Use gsl-library. Alternative is WITH_BOOST" ON) option(PARALLELIZED_SOLVERS "Use parallel version of GSOLVE. (alpha)" OFF ) -option(PARALLELIZED_CLOCK "High level parallelization of moose::Clock (alpha)" OFF ) +option(PARALLELIZED_CLOCK "High level parallelization of moose::Clock (alpha)" OFF ) + +option(USE_PRIVATE_RNG "Stochastic Objects use their private RNG" ON) ############################ BUILD CONFIGURATION ################################# -# Default macros +# Default definitions. add_definitions(-DUSE_GENESIS_PARSER) -if(DEBUG) +if(DEBUG OR "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") message(STATUS "Building for Debug/Unit testing") add_definitions(-DDO_UNIT_TESTS) set(CMAKE_BUILD_TYPE Debug) @@ -114,15 +104,22 @@ elseif(ENABLE_UNIT_TESTS) else() message(STATUS "Building for Release/No unit tests.") set(CMAKE_BUILD_TYPE Release) - add_definitions(-UDO_UNIT_TESTS -DQUIET_MODE -O3) + add_definitions(-UDO_UNIT_TESTS -O3 -DDISABLE_DEBUG) + # Treat all warnings as errors. Some the warnings are disabled in + # CheckCXXCompiler.cmake . + add_definitions(-Werror) endif() -if(GPROF AND DEBUG) +if(GPROF AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") message(STATUS "Compiling with profiling with gprof") add_definitions(-pg) set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg") endif() +if(PARALLELIZED_SOLVERS) + find_package(Threads) +endif() + ################################### TARGETS #################################### @@ -134,9 +131,10 @@ add_executable(moose.bin basecode/main.cpp) # default include paths. include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -if(WITH_BOOST) +# If using BOOST ODE2 library to solve ODE system, then don't use GSL. +if(WITH_BOOST_ODE) set(WITH_GSL OFF) -endif(WITH_BOOST) +endif(WITH_BOOST_ODE) include_directories(msg basecode) @@ -148,6 +146,12 @@ set(STATIC_LIBRARIES "" ) # Collect all shared libraries here. set(SYSTEM_SHARED_LIBS ${LibXML2_LIBRARIES}) +# BOOST ode library performs better than GSL and ideally should be made default. +# Making boost default means that we get rid of gsl. Boost does not have a very +# good matrix library; it has ublas which is not well maintained and emit a lot +# of warning during compilation. Nonetheless, WITH_BOOST_ODE works fine and +# produce results quicker than GSL. Both boost ode and ublas are in moose source +# tree ./external/odeint-v2 and ./external/boost-numeric-bindings if(WITH_GSL) find_package(GSL 1.16 REQUIRED) if(NOT GSL_FOUND) @@ -171,18 +175,14 @@ if(WITH_GSL) # GSL is also used in RNG (whenever applicable), therefore include paths are # top level. include_directories( ${GSL_INCLUDE_DIRS} ) -elseif(WITH_BOOST) - find_package(Boost 1.44 COMPONENTS system filesystem random REQUIRED) +elseif(WITH_BOOST_ODE) + find_package(Boost 1.44 REQUIRED) find_package( LAPACK REQUIRED ) - add_definitions( -DUSE_BOOST -UUSE_GSL ) - include_directories( ${Boost_INCLUDE_DIRS} ) - check_include_file_cxx( - ${Boost_INCLUDE_DIRS}/boost/random/random_device.hpp - BOOST_RANDOM_DEVICE_EXISTS - ) - if(BOOST_RANDOM_DEVICE_EXISTS) - add_definitions(-DBOOST_RANDOM_DEVICE_EXISTS) - endif(BOOST_RANDOM_DEVICE_EXISTS) +endif() + +# if boost ode is being used, don't use GSL. +if(WITH_BOOST_ODE) + add_definitions(-DUSE_BOOST_ODE -UUSE_GSL) endif() @@ -264,10 +264,14 @@ if(WITH_MPI) endif() endif(WITH_MPI) -if(WITH_BOOST) +if(WITH_BOOST_ODE) list(APPEND SYSTEM_SHARED_LIBS ${LAPACK_LIBRARIES}) list(APPEND SYSTEM_SHARED_LIBS ${Boost_LIBRARIES}) -endif(WITH_BOOST) +endif(WITH_BOOST_ODE) + +if(PARALLELIZED_SOLVERS) + list(APPEND SYSTEM_SHARED_LIBS ${CMAKE_THREAD_LIBS_INIT}) +endif() # These libraries could be static of dynamic. We need to discrimate between # these two types because of --whole-archive option. See @@ -330,7 +334,6 @@ list(APPEND MOOSE_LIBRARIES msg benchmarks shell - randnum scheduling moose_mpi biophysics @@ -483,13 +486,13 @@ include( CTest ) # onto the console if a test fails. set(ENV{CTEST_OUTPUT_ON_FAILURE} ON) -if(DEBUG) +if(DEBUG OR "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") # Run this test in debug mode. In Release mode, this does not do anything. set(MOOSE_BIN_LOCATION $<TARGET_FILE:moose.bin>) message(STATUS "Executable moose.bin will be at ${MOOSE_BIN_LOCATION}" ) add_test(NAME moose.bin-raw-run COMMAND moose.bin -u -q) -endif(DEBUG) +endif() ## PyMOOSE tests. set(PYMOOSE_TEST_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/python) diff --git a/moose-core/CheckCXXCompiler.cmake b/moose-core/CheckCXXCompiler.cmake index 92fbfdfa3c57c433baf213930c59c61300b088a7..f3fe24d921de0a6220fa427c91c02e9a37ac26dd 100644 --- a/moose-core/CheckCXXCompiler.cmake +++ b/moose-core/CheckCXXCompiler.cmake @@ -5,15 +5,17 @@ CHECK_CXX_COMPILER_FLAG( "-std=c++11" COMPILER_SUPPORTS_CXX11 ) CHECK_CXX_COMPILER_FLAG( "-std=c++0x" COMPILER_SUPPORTS_CXX0X ) CHECK_CXX_COMPILER_FLAG( "-Wno-strict-aliasing" COMPILER_WARNS_STRICT_ALIASING ) - # Turn warning to error: Not all of the options may be supported on all # versions of compilers. be careful here. add_definitions(-Wall #-Wno-return-type-c-linkage - -Wno-unused-variable + -Wno-unused-variable -Wno-unused-function + -Wno-unused-local-typedefs #-Wno-unused-private-field ) + + add_definitions(-fPIC) if(COMPILER_WARNS_STRICT_ALIASING) add_definitions( -Wno-strict-aliasing ) @@ -32,7 +34,9 @@ if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") add_definitions( -DENABLE_CPP11 ) if(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) + message(STATUS "NOTE: Making clang to inline more aggresively" ) + add_definitions( -mllvm -inline-threshold=1000 ) endif(APPLE) else(COMPILER_SUPPORTS_CXX11) add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS -DBOOST_NO_SCOPED_ENUMS ) diff --git a/moose-core/MANIFEST.in b/moose-core/MANIFEST.in deleted file mode 100644 index 8572af5e481e05ddbd78e81fcbf38f61d5a6f8c4..0000000000000000000000000000000000000000 --- a/moose-core/MANIFEST.in +++ /dev/null @@ -1,15 +0,0 @@ -global-include *.h -global-include *.cpp -global-include *.c -global-include configure.ac -global-include *.hpp -global-include *.cc -global-include *.py -global-include CMakeLists.txt -include README -graft cmake_modules -graft gsl -graft external -graft Demos -graft Docs -prune buildMooseUsingCmake diff --git a/moose-core/README.md b/moose-core/README.md index dd8e63621de6d0da31186fdb10fd7f940c15e276..6e5ed75a7f0ca38b0fe1b561ee92a733fef38796 100644 --- a/moose-core/README.md +++ b/moose-core/README.md @@ -1,4 +1,4 @@ -[](https://travis-ci.org/BhallaLab/moose-core) | [](https://badge.fury.io/py/pymoose) +[](https://travis-ci.org/BhallaLab/moose-core) | [](https://badge.fury.io/py/pymoose) | [Nightly Linux Build on OBS](https://software.opensuse.org//download.html?project=home%3Amoose&package=pymoose) This is the core computational engine of [MOOSE simulator](https://github.com/BhallaLab/moose). This repository contains C++ codebase and python interface called `pymoose`. For more details about MOOSE simulator, visit https://moose.ncbs.res.in . diff --git a/moose-core/basecode/Id.h b/moose-core/basecode/Id.h index 9aed5e9beac5e6cf1b7ac6b57317d1c00da827db..1b877e0b3812fb3e560717564b906caff3964774 100644 --- a/moose-core/basecode/Id.h +++ b/moose-core/basecode/Id.h @@ -174,13 +174,19 @@ private: static vector< Element* >& elements(); }; -namespace std { - template <> class hash<Id>{ - public : - size_t operator()(const Id &x ) const{ - return hash<unsigned int>()( x.value() ); - } - }; +// User defined hash function. +// See https://en.cppreference.com/w/cpp/utility/hash for more details. +namespace std +{ + template <> + struct hash<Id> + { + public : + size_t operator()(const Id &x ) const + { + return std::hash<unsigned int>()( x.value() ); + } + }; } #endif // _ID_H diff --git a/moose-core/basecode/SparseMatrix.cpp b/moose-core/basecode/SparseMatrix.cpp index b5d2acc47c27de48beeb443c553951741bad3bdf..0f1de408479f812331e7cd4cec509fa34bca5d36 100644 --- a/moose-core/basecode/SparseMatrix.cpp +++ b/moose-core/basecode/SparseMatrix.cpp @@ -8,8 +8,6 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -using namespace std; - #include <algorithm> #include <vector> #include <map> @@ -17,6 +15,8 @@ using namespace std; #include <iostream> #include "SparseMatrix.h" +using namespace std; + const unsigned int SM_MAX_ROWS = 200000; const unsigned int SM_MAX_COLUMNS = 200000; diff --git a/moose-core/basecode/global.cpp b/moose-core/basecode/global.cpp index 09ebeaa300be9dc29178ca89533ba62c242d773c..90f82b6ba10d09363c762824c22445af309a3bb1 100644 --- a/moose-core/basecode/global.cpp +++ b/moose-core/basecode/global.cpp @@ -40,10 +40,9 @@ extern string joinPath( string pathA, string pathB); extern string fixPath( string path); extern string dumpStats( int ); - namespace moose { - int __rng_seed__ = 0; + unsigned long __rng_seed__ = 0; moose::RNG<double> rng; @@ -131,29 +130,13 @@ namespace moose { p = p.substr( 0, pos ); else /* no parent directory to create */ return true; + if( p.size() == 0 ) return true; -#ifdef USE_BOOST - try - { - boost::filesystem::path pdirs( p ); - boost::filesystem::create_directories( pdirs ); - LOG( moose::info, "Created directory " << p ); - return true; - } - catch(const boost::filesystem::filesystem_error& e) - { - LOG( moose::warning, "create_directories(" << p << ") failed with " - << e.code().message() - ); - return false; - } -#else /* ----- not USE_BOOST ----- */ string command( "mkdir -p "); command += p; int ret = system( command.c_str() ); - cout << "+ Return code " << ret << endl; struct stat info; if( stat( p.c_str(), &info ) != 0 ) { @@ -170,7 +153,6 @@ namespace moose { LOG( moose::warning, p << " is no directory" ); return false; } -#endif /* ----- not USE_BOOST ----- */ return true; } @@ -221,4 +203,13 @@ namespace moose { return string( buffer ); } + int getGlobalSeed( ) + { + return __rng_seed__; + } + + void setGlobalSeed( int seed ) + { + __rng_seed__ = seed; + } } diff --git a/moose-core/basecode/global.h b/moose-core/basecode/global.h index 761a310f89f73cf6b4499a559ad3c206191fb78e..1735595d9a203fdcddb98f510f11ef107eaa8385 100644 --- a/moose-core/basecode/global.h +++ b/moose-core/basecode/global.h @@ -16,14 +16,7 @@ #include <map> #include <sstream> - -#ifdef USE_BOOST -//#ifdef BOOST_FILESYSTEM_EXISTS -#include <boost/filesystem.hpp> -//#endif /* BOOST_FILESYSTEM_EXISTS */ -#endif - -#include "randnum/RNG.h" /* Use inbuilt rng */ +#include "../randnum/RNG.h" /* Use inbuilt rng */ #include "../utility/print_function.hpp" using namespace std; @@ -70,7 +63,7 @@ namespace moose * initialize them. By default it is initialized by random_device (see * global.cpp). */ - extern int __rng_seed__; + extern unsigned long __rng_seed__; /** * @brief Fix a path. For testing purpose. @@ -183,6 +176,24 @@ namespace moose */ string moosePathToUserPath( string path ); + /* --------------------------------------------------------------------------*/ + /** + * @Synopsis Get the global seed set by call of moose.seed( X ) + * + * @Returns seed (int). + */ + /* ----------------------------------------------------------------------------*/ + int getGlobalSeed( ); + + /* --------------------------------------------------------------------------*/ + /** + * @Synopsis Set the seed for all random generator. When seed of a RNG is + * not set, this seed it used. It is set to -1 by default. + * + * @Param seed + */ + /* ----------------------------------------------------------------------------*/ + void setGlobalSeed( int seed ); } #endif /* ----- #ifndef __MOOSE_GLOBAL_INC_ ----- */ diff --git a/moose-core/basecode/main.cpp b/moose-core/basecode/main.cpp index d6b2822623007c0be89094ddf507b56e8d113e8b..cde0f33dc9292430bd7c23ec4b237cc28d54935e 100644 --- a/moose-core/basecode/main.cpp +++ b/moose-core/basecode/main.cpp @@ -8,6 +8,7 @@ **********************************************************************/ #include "header.h" +#include "SparseMatrix.h" #ifndef WIN32 #include <sys/time.h> @@ -22,9 +23,8 @@ #include <unistd.h> // for getopt #endif #include "../scheduling/Clock.h" -#include "DiagonalMsg.h" -#include "SparseMatrix.h" -#include "SparseMsg.h" +#include "../msg/DiagonalMsg.h" +#include "../msg/SparseMsg.h" #include "../mpi/PostMaster.h" #ifdef USE_MPI #include <mpi.h> diff --git a/moose-core/basecode/testAsync.cpp b/moose-core/basecode/testAsync.cpp index b615611b9f62ab724b91141796a7669086d85965..3ba2b25057b17eabdc55e334670324713eb1beb6 100644 --- a/moose-core/basecode/testAsync.cpp +++ b/moose-core/basecode/testAsync.cpp @@ -6,47 +6,36 @@ ** GNU Lesser General Public License version 2.1 ** See the file COPYING.LIB for the full notice. **********************************************************************/ +#include <stdio.h> +#include <iomanip> #include "header.h" #include "global.h" - -#include <stdio.h> -#include <iomanip> -#include "../shell/Neutral.h" -#include "../builtins/Arith.h" #include "Dinfo.h" -#include <queue> -#include "../biophysics/IntFire.h" +#include "SparseMatrix.h" + +#include "../msg/OneToOneMsg.h" +#include "../msg/SparseMsg.h" +#include "../msg/SingleMsg.h" + #include "../synapse/Synapse.h" #include "../synapse/SynEvent.h" #include "../synapse/SynHandlerBase.h" #include "../synapse/SimpleSynHandler.h" -#include "SparseMatrix.h" -#include "SparseMsg.h" -#include "SingleMsg.h" -#include "OneToOneMsg.h" -#include "../scheduling/Clock.h" #include "../shell/Shell.h" +#include "../shell/Neutral.h" + #include "../mpi/PostMaster.h" +#include "../scheduling/Clock.h" +#include "../builtins/Arith.h" +#include "../biophysics/IntFire.h" +#include "../randnum/RNG.h" -#include "randnum/RNG.h" +#include <queue> int _seed_ = 0; -moose::RNG<double> rng_; - -void _mtseed_( unsigned int seed ) -{ - _seed_ = seed; - rng_.setSeed( _seed_ ); -} - -double _mtrand_( ) -{ - return rng_.uniform( ); -} - void showFields() { const Cinfo* nc = Neutral::initCinfo(); @@ -818,7 +807,8 @@ void testSparseMsg() string arg; - _mtseed_( 5489UL ); // The default value, but better to be explicit. + // The default value, but better to be explicit. + moose::setGlobalSeed( 5489UL ); Id sshid = Id::nextId(); Element* t2 = new GlobalDataElement( sshid, sshc, "test2", size ); @@ -838,7 +828,7 @@ void testSparseMsg() vector< double > temp( size, 0.0 ); for ( unsigned int i = 0; i < size; ++i ) - temp[i] = _mtrand_() * Vmax; + temp[i] = moose::mtrand() * Vmax; bool ret = Field< double >::setVec( cells, "Vm", temp ); assert( ret ); @@ -860,8 +850,8 @@ void testSparseMsg() Field< unsigned int >::get( id, "numSynapse" ); unsigned int k = i * fieldSize; for ( unsigned int j = 0; j < numSyn; ++j ) { - weight[ k + j ] = _mtrand_() * weightMax; - delay[ k + j ] = _mtrand_() * delayMax; + weight[ k + j ] = moose::mtrand() * weightMax; + delay[ k + j ] = moose::mtrand() * delayMax; } } ret = Field< double >::setVec( syns, "weight", weight ); diff --git a/moose-core/biophysics/Compartment.cpp b/moose-core/biophysics/Compartment.cpp index dda3ee47cfe3645a4a9efc3df895b4d9ad7f58ea..8a137df7d39497e5ef7b0d967a59076983751c14 100644 --- a/moose-core/biophysics/Compartment.cpp +++ b/moose-core/biophysics/Compartment.cpp @@ -7,8 +7,8 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" -#include "../randnum/randnum.h" +#include "../basecode/header.h" +#include "../basecode/global.h" #include "CompartmentBase.h" #include "Compartment.h" @@ -25,29 +25,29 @@ const double Compartment::EPSILON = 1.0e-15; */ const Cinfo* Compartment::initCinfo() { - /////////////////////////////////////////////////////////////////// - // static Finfo* compartmentFinfos[] = { }; - - static string doc[] = - { - "Name", "Compartment", - "Author", "Upi Bhalla", - "Description", "Compartment object, for branching neuron models.", - }; + /////////////////////////////////////////////////////////////////// + // static Finfo* compartmentFinfos[] = { }; + + static string doc[] = + { + "Name", "Compartment", + "Author", "Upi Bhalla", + "Description", "Compartment object, for branching neuron models.", + }; static Dinfo< Compartment > dinfo; - static Cinfo compartmentCinfo( - "Compartment", - CompartmentBase::initCinfo(), - 0, - 0, - // compartmentFinfos, - // sizeof( compartmentFinfos ) / sizeof( Finfo* ), - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); - - return &compartmentCinfo; + static Cinfo compartmentCinfo( + "Compartment", + CompartmentBase::initCinfo(), + 0, + 0, + // compartmentFinfos, + // sizeof( compartmentFinfos ) / sizeof( Finfo* ), + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); + + return &compartmentCinfo; } static const Cinfo* compartmentCinfo = Compartment::initCinfo(); @@ -60,12 +60,12 @@ const SrcFinfo1< double >* VmOut = */ const SrcFinfo1< double >* axialOut = - dynamic_cast< const SrcFinfo1< double >* > ( - compartmentCinfo->findFinfo( "axialOut" ) ); + dynamic_cast< const SrcFinfo1< double >* > ( + compartmentCinfo->findFinfo( "axialOut" ) ); const SrcFinfo2< double, double >* raxialOut = - dynamic_cast< const SrcFinfo2< double, double >* > ( - compartmentCinfo->findFinfo( "raxialOut" ) ); + dynamic_cast< const SrcFinfo2< double, double >* > ( + compartmentCinfo->findFinfo( "raxialOut" ) ); ////////////////////////////////////////////////////////////////// // Here we put the Compartment class functions. @@ -73,104 +73,104 @@ const SrcFinfo2< double, double >* raxialOut = Compartment::Compartment() { - Vm_ = -0.06; - Em_ = -0.06; - Cm_ = 1.0; - Rm_ = 1.0; - invRm_ = 1.0; - Ra_ = 1.0; - Im_ = 0.0; + Vm_ = -0.06; + Em_ = -0.06; + Cm_ = 1.0; + Rm_ = 1.0; + invRm_ = 1.0; + Ra_ = 1.0; + Im_ = 0.0; lastIm_ = 0.0; - inject_ = 0.0; - sumInject_ = 0.0; - initVm_ = -0.06; - A_ = 0.0; - B_ = 0.0; + inject_ = 0.0; + sumInject_ = 0.0; + initVm_ = -0.06; + A_ = 0.0; + B_ = 0.0; } Compartment::~Compartment() { - ; + ; } // Value Field access function definitions. void Compartment::vSetVm( const Eref& e, double Vm ) { - Vm_ = Vm; + Vm_ = Vm; } double Compartment::vGetVm( const Eref& e ) const { - return Vm_; + return Vm_; } void Compartment::vSetEm( const Eref& e, double Em ) { - Em_ = Em; + Em_ = Em; } double Compartment::vGetEm( const Eref& e ) const { - return Em_; + return Em_; } void Compartment::vSetCm( const Eref& e, double Cm ) { - if ( rangeWarning( "Cm", Cm ) ) return; - Cm_ = Cm; + if ( rangeWarning( "Cm", Cm ) ) return; + Cm_ = Cm; } double Compartment::vGetCm( const Eref& e ) const { - return Cm_; + return Cm_; } void Compartment::vSetRm( const Eref& e, double Rm ) { - if ( rangeWarning( "Rm", Rm ) ) return; - Rm_ = Rm; - invRm_ = 1.0/Rm; + if ( rangeWarning( "Rm", Rm ) ) return; + Rm_ = Rm; + invRm_ = 1.0/Rm; } double Compartment::vGetRm( const Eref& e ) const { - return Rm_; + return Rm_; } void Compartment::vSetRa( const Eref& e, double Ra ) { - if ( rangeWarning( "Ra", Ra ) ) return; - Ra_ = Ra; + if ( rangeWarning( "Ra", Ra ) ) return; + Ra_ = Ra; } double Compartment::vGetRa( const Eref& e ) const { - return Ra_; + return Ra_; } double Compartment::vGetIm( const Eref& e ) const { - return lastIm_; + return lastIm_; } void Compartment::vSetInject( const Eref& e, double inject ) { - inject_ = inject; + inject_ = inject; } double Compartment::vGetInject( const Eref& e ) const { - return inject_; + return inject_; } void Compartment::vSetInitVm( const Eref& e, double initVm ) { - initVm_ = initVm; + initVm_ = initVm; } double Compartment::vGetInitVm( const Eref& e ) const { - return initVm_; + return initVm_; } @@ -180,84 +180,88 @@ double Compartment::vGetInitVm( const Eref& e ) const void Compartment::vProcess( const Eref& e, ProcPtr p ) { - //cout << "Compartment " << e.id().path() << ":: process: A = " << A_ << ", B = " << B_ << endl; - A_ += inject_ + sumInject_ + Em_ * invRm_; - if ( B_ > EPSILON ) { - double x = exp( -B_ * p->dt / Cm_ ); - Vm_ = Vm_ * x + ( A_ / B_ ) * ( 1.0 - x ); - } else { - Vm_ += ( A_ - Vm_ * B_ ) * p->dt / Cm_; - } - A_ = 0.0; - B_ = invRm_; - lastIm_ = Im_; - Im_ = 0.0; - sumInject_ = 0.0; - // Send out Vm to channels, SpikeGens, etc. - VmOut()->send( e, Vm_ ); - - // The axial/raxial messages go out in the 'init' phase. + //cout << "Compartment " << e.id().path() << ":: process: A = " << A_ << ", B = " << B_ << endl; + A_ += inject_ + sumInject_ + Em_ * invRm_; + if ( B_ > EPSILON ) + { + double x = exp( -B_ * p->dt / Cm_ ); + Vm_ = Vm_ * x + ( A_ / B_ ) * ( 1.0 - x ); + } + else + { + Vm_ += ( A_ - Vm_ * B_ ) * p->dt / Cm_; + } + A_ = 0.0; + B_ = invRm_; + lastIm_ = Im_; + Im_ = 0.0; + sumInject_ = 0.0; + // Send out Vm to channels, SpikeGens, etc. + VmOut()->send( e, Vm_ ); + + // The axial/raxial messages go out in the 'init' phase. } void Compartment::vReinit( const Eref& e, ProcPtr p ) { - Vm_ = initVm_; - A_ = 0.0; - B_ = invRm_; - Im_ = 0.0; - lastIm_ = 0.0; - sumInject_ = 0.0; - dt_ = p->dt; - - // Send out the resting Vm to channels, SpikeGens, etc. - VmOut()->send( e, Vm_ ); + Vm_ = initVm_; + A_ = 0.0; + B_ = invRm_; + Im_ = 0.0; + lastIm_ = 0.0; + sumInject_ = 0.0; + dt_ = p->dt; + + // Send out the resting Vm to channels, SpikeGens, etc. + VmOut()->send( e, Vm_ ); } void Compartment::vInitProc( const Eref& e, ProcPtr p ) { - // Send out the axial messages - axialOut->send( e, Vm_ ); - // Send out the raxial messages - raxialOut->send( e, Ra_, Vm_ ); + // Send out the axial messages + axialOut->send( e, Vm_ ); + // Send out the raxial messages + raxialOut->send( e, Ra_, Vm_ ); } void Compartment::vInitReinit( const Eref& e, ProcPtr p ) { - ; // Nothing happens here + ; // Nothing happens here } void Compartment::vHandleChannel( const Eref& e, double Gk, double Ek) { - A_ += Gk * Ek; - B_ += Gk; + A_ += Gk * Ek; + B_ += Gk; } void Compartment::vHandleRaxial( double Ra, double Vm) { - A_ += Vm / Ra; - B_ += 1.0 / Ra; - Im_ += ( Vm - Vm_ ) / Ra; + A_ += Vm / Ra; + B_ += 1.0 / Ra; + Im_ += ( Vm - Vm_ ) / Ra; } void Compartment::vHandleAxial( double Vm) { - A_ += Vm / Ra_; - B_ += 1.0 / Ra_; - Im_ += ( Vm - Vm_ ) / Ra_; + A_ += Vm / Ra_; + B_ += 1.0 / Ra_; + Im_ += ( Vm - Vm_ ) / Ra_; } void Compartment::vInjectMsg( const Eref& e, double current) { - sumInject_ += current; - Im_ += current; + sumInject_ += current; + Im_ += current; } void Compartment::vRandInject( const Eref& e, double prob, double current) { - if ( mtrand() < prob * dt_ ) { - sumInject_ += current; - Im_ += current; - } + if ( moose::mtrand() < prob * dt_ ) + { + sumInject_ += current; + Im_ += current; + } } ///////////////////////////////////////////////////////////////////// @@ -270,39 +274,39 @@ void Compartment::vRandInject( const Eref& e, double prob, double current) void testCompartment() { - unsigned int size = 1; - Eref sheller( Id().eref() ); - Shell* shell = reinterpret_cast< Shell* >( sheller.data() ); - Id comptId = shell->doCreate("Compartment", Id(), "compt", size); - assert( Id::isValid(comptId)); - Eref compter = comptId.eref(); - Compartment* c = reinterpret_cast< Compartment* >( comptId.eref().data() ); - ProcInfo p; - p.dt = 0.002; - c->setInject( compter, 1.0 ); - c->setRm( compter, 1.0 ); - c->setRa( compter, 0.0025 ); - c->setCm( compter, 1.0 ); - c->setEm( compter, 0.0 ); - c->setVm( compter, 0.0 ); - - // First, test charging curve for a single compartment - // We want our charging curve to be a nice simple exponential - // Vm = 1.0 - 1.0 * exp( - t / 1.0 ); - double delta = 0.0; - double Vm = 0.0; - double tau = 1.0; - double Vmax = 1.0; - for ( p.currTime = 0.0; p.currTime < 2.0; p.currTime += p.dt ) - { - Vm = c->getVm( compter ); - double x = Vmax - Vmax * exp( -p.currTime / tau ); - delta += ( Vm - x ) * ( Vm - x ); - c->process( compter, &p ); - } - assert( delta < 1.0e-6 ); - shell->doDelete(comptId); - cout << "." << flush; + unsigned int size = 1; + Eref sheller( Id().eref() ); + Shell* shell = reinterpret_cast< Shell* >( sheller.data() ); + Id comptId = shell->doCreate("Compartment", Id(), "compt", size); + assert( Id::isValid(comptId)); + Eref compter = comptId.eref(); + Compartment* c = reinterpret_cast< Compartment* >( comptId.eref().data() ); + ProcInfo p; + p.dt = 0.002; + c->setInject( compter, 1.0 ); + c->setRm( compter, 1.0 ); + c->setRa( compter, 0.0025 ); + c->setCm( compter, 1.0 ); + c->setEm( compter, 0.0 ); + c->setVm( compter, 0.0 ); + + // First, test charging curve for a single compartment + // We want our charging curve to be a nice simple exponential + // Vm = 1.0 - 1.0 * exp( - t / 1.0 ); + double delta = 0.0; + double Vm = 0.0; + double tau = 1.0; + double Vmax = 1.0; + for ( p.currTime = 0.0; p.currTime < 2.0; p.currTime += p.dt ) + { + Vm = c->getVm( compter ); + double x = Vmax - Vmax * exp( -p.currTime / tau ); + delta += ( Vm - x ) * ( Vm - x ); + c->process( compter, &p ); + } + assert( delta < 1.0e-6 ); + shell->doDelete(comptId); + cout << "." << flush; } // Comment out this define if it takes too long (about 5 seconds on @@ -319,72 +323,73 @@ void testCompartment() #include "../shell/Shell.h" void testCompartmentProcess() { - Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); - unsigned int size = 100; - double Rm = 1.0; - double Ra = 0.01; - double Cm = 1.0; - double dt = 0.01; - double runtime = 10; - double lambda = sqrt( Rm / Ra ); - - Id cid = shell->doCreate( "Compartment", Id(), "compt", size ); - assert( Id::isValid(cid)); - assert( cid.eref().element()->numData() == size ); - - bool ret = Field< double >::setRepeat( cid, "initVm", 0.0 ); - assert( ret ); - Field< double >::setRepeat( cid, "inject", 0 ); - // Only apply current injection in first compartment - Field< double >::set( ObjId( cid, 0 ), "inject", 1.0 ); - Field< double >::setRepeat( cid, "Rm", Rm ); - Field< double >::setRepeat( cid, "Ra", Ra ); - Field< double >::setRepeat( cid, "Cm", Cm ); - Field< double >::setRepeat( cid, "Em", 0 ); - Field< double >::setRepeat( cid, "Vm", 0 ); - - // The diagonal message has a default stride of 1, so it connects - // successive compartments. - // Note that the src and dest elements here are identical, so we cannot - // use a shared message. The messaging system will get confused about - // direction to send data. So we split up the shared message that we - // might have used, below, into two individual messages. - // MsgId mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "raxial", ObjId( cid ), "axial" ); - ObjId mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "axialOut", ObjId( cid ), "handleAxial" ); - assert( !mid.bad()); - // mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "handleRaxial", ObjId( cid ), "raxialOut" ); - mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "raxialOut", ObjId( cid ), "handleRaxial" ); - assert( !mid.bad() ); - // ObjId managerId = Msg::getMsg( mid )->manager().objId(); - // Make the raxial data go from high to lower index compartments. - Field< int >::set( mid, "stride", -1 ); + Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); + unsigned int size = 100; + double Rm = 1.0; + double Ra = 0.01; + double Cm = 1.0; + double dt = 0.01; + double runtime = 10; + double lambda = sqrt( Rm / Ra ); + + Id cid = shell->doCreate( "Compartment", Id(), "compt", size ); + assert( Id::isValid(cid)); + assert( cid.eref().element()->numData() == size ); + + bool ret = Field< double >::setRepeat( cid, "initVm", 0.0 ); + assert( ret ); + Field< double >::setRepeat( cid, "inject", 0 ); + // Only apply current injection in first compartment + Field< double >::set( ObjId( cid, 0 ), "inject", 1.0 ); + Field< double >::setRepeat( cid, "Rm", Rm ); + Field< double >::setRepeat( cid, "Ra", Ra ); + Field< double >::setRepeat( cid, "Cm", Cm ); + Field< double >::setRepeat( cid, "Em", 0 ); + Field< double >::setRepeat( cid, "Vm", 0 ); + + // The diagonal message has a default stride of 1, so it connects + // successive compartments. + // Note that the src and dest elements here are identical, so we cannot + // use a shared message. The messaging system will get confused about + // direction to send data. So we split up the shared message that we + // might have used, below, into two individual messages. + // MsgId mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "raxial", ObjId( cid ), "axial" ); + ObjId mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "axialOut", ObjId( cid ), "handleAxial" ); + assert( !mid.bad()); + // mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "handleRaxial", ObjId( cid ), "raxialOut" ); + mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "raxialOut", ObjId( cid ), "handleRaxial" ); + assert( !mid.bad() ); + // ObjId managerId = Msg::getMsg( mid )->manager().objId(); + // Make the raxial data go from high to lower index compartments. + Field< int >::set( mid, "stride", -1 ); #ifdef DO_SPATIAL_TESTS - shell->doSetClock( 0, dt ); - shell->doSetClock( 1, dt ); - // Ensure that the inter_compt msgs go between nodes once every dt. - shell->doSetClock( 9, dt ); - - shell->doUseClock( "/compt", "init", 0 ); - shell->doUseClock( "/compt", "process", 1 ); - - shell->doReinit(); - shell->doStart( runtime ); - - double Vmax = Field< double >::get( ObjId( cid, 0 ), "Vm" ); - - double delta = 0.0; - // We measure only the first 50 compartments as later we - // run into end effects because it is not an infinite cable - for ( unsigned int i = 0; i < size; i++ ) { - double Vm = Field< double >::get( ObjId( cid, i ), "Vm" ); - double x = Vmax * exp( - static_cast< double >( i ) / lambda ); - delta += ( Vm - x ) * ( Vm - x ); - // cout << i << " (x, Vm) = ( " << x << ", " << Vm << " )\n"; - } - assert( delta < 1.0e-5 ); + shell->doSetClock( 0, dt ); + shell->doSetClock( 1, dt ); + // Ensure that the inter_compt msgs go between nodes once every dt. + shell->doSetClock( 9, dt ); + + shell->doUseClock( "/compt", "init", 0 ); + shell->doUseClock( "/compt", "process", 1 ); + + shell->doReinit(); + shell->doStart( runtime ); + + double Vmax = Field< double >::get( ObjId( cid, 0 ), "Vm" ); + + double delta = 0.0; + // We measure only the first 50 compartments as later we + // run into end effects because it is not an infinite cable + for ( unsigned int i = 0; i < size; i++ ) + { + double Vm = Field< double >::get( ObjId( cid, i ), "Vm" ); + double x = Vmax * exp( - static_cast< double >( i ) / lambda ); + delta += ( Vm - x ) * ( Vm - x ); + // cout << i << " (x, Vm) = ( " << x << ", " << Vm << " )\n"; + } + assert( delta < 1.0e-5 ); #endif // DO_SPATIAL_TESTS - shell->doDelete( cid ); - cout << "." << flush; + shell->doDelete( cid ); + cout << "." << flush; } #endif // DO_UNIT_TESTS diff --git a/moose-core/biophysics/Compartment.h b/moose-core/biophysics/Compartment.h index b5c3de0455466edc5f8367841294937bb024b788..af2186bbef412765d63f550e6016ee985c800d04 100644 --- a/moose-core/biophysics/Compartment.h +++ b/moose-core/biophysics/Compartment.h @@ -21,117 +21,119 @@ namespace moose { class Compartment: public CompartmentBase { - public: - Compartment(); - virtual ~Compartment(); - - // Value Field access function definitions. - virtual void vSetVm( const Eref& e, double Vm ); - virtual double vGetVm( const Eref& e ) const; - virtual void vSetEm( const Eref& e, double Em ); - virtual double vGetEm( const Eref& e ) const; - virtual void vSetCm( const Eref& e, double Cm ); - virtual double vGetCm( const Eref& e ) const; - virtual void vSetRm( const Eref& e, double Rm ); - virtual double vGetRm( const Eref& e ) const; - virtual void vSetRa( const Eref& e, double Ra ); - virtual double vGetRa( const Eref& e ) const; - virtual double vGetIm( const Eref& e ) const; - virtual void vSetInject( const Eref& e, double Inject ); - virtual double vGetInject( const Eref& e ) const; - virtual void vSetInitVm( const Eref& e, double initVm ); - virtual double vGetInitVm( const Eref& e ) const; - - // Dest function definitions. - /** - * The process function does the object updating and sends out - * messages to channels, nernsts, and so on. - */ - void vProcess( const Eref& e, ProcPtr p ); - - /** - * The reinit function reinitializes all fields. - */ - void vReinit( const Eref& e, ProcPtr p ); - - /** - * The initProc function is for a second phase of 'process' - * operations. It sends the axial and raxial messages - * to other compartments. It has to be executed out of phase - * with the main process so that all compartments are - * equivalent and there is no calling order dependence in - * the results. - */ - void vInitProc( const Eref& e, ProcPtr p ); - - /** - * Empty function to do another reinit step out of phase - * with the main one. Nothing needs doing there. - */ - void vInitReinit( const Eref& e, ProcPtr p ); - - /** - * handleChannel handles information coming from the channel - * to the compartment - */ - void vHandleChannel( const Eref& e, double Gk, double Ek); - - /** - * handleRaxial handles incoming raxial message data. - */ - void vHandleRaxial( double Ra, double Vm); - - /** - * handleAxial handles incoming axial message data. - */ - void vHandleAxial( double Vm); - - /** - * Injects a constantly updated current into the compartment. - * Unlike the 'inject' field, this injected current is - * applicable only for a single timestep. So this is meant to - * be used as the destination of a message rather than as a - * one-time assignment. - */ - void vInjectMsg( const Eref& e, double current); - - /** - * Injects a constantly updated current into the - * compartment, with a probability prob. Note that it isn't - * the current amplitude that is random, it is the presence - * or absence of the current that is probabilistic. - */ - void vRandInject( const Eref& e, double prob, double current); - - /** - * Dummy function to act as recipient of 'cable' message, - * which is just for grouping compartments. - */ - void cable(); - - - /** - * Initializes the class info. - */ - static const Cinfo* initCinfo(); - protected: - double Vm_; - double initVm_; - double Em_; - double Cm_; - double Rm_; - double Ra_; - double Im_; - double lastIm_; - double inject_; - double A_; - double B_; - double sumInject_; - - private: - double invRm_; - double dt_; - static const double EPSILON; +public: + Compartment(); + virtual ~Compartment(); + + // Value Field access function definitions. + virtual void vSetVm( const Eref& e, double Vm ); + virtual double vGetVm( const Eref& e ) const; + virtual void vSetEm( const Eref& e, double Em ); + virtual double vGetEm( const Eref& e ) const; + virtual void vSetCm( const Eref& e, double Cm ); + virtual double vGetCm( const Eref& e ) const; + virtual void vSetRm( const Eref& e, double Rm ); + virtual double vGetRm( const Eref& e ) const; + virtual void vSetRa( const Eref& e, double Ra ); + virtual double vGetRa( const Eref& e ) const; + virtual double vGetIm( const Eref& e ) const; + virtual void vSetInject( const Eref& e, double Inject ); + virtual double vGetInject( const Eref& e ) const; + virtual void vSetInitVm( const Eref& e, double initVm ); + virtual double vGetInitVm( const Eref& e ) const; + + // Dest function definitions. + /** + * The process function does the object updating and sends out + * messages to channels, nernsts, and so on. + */ + void vProcess( const Eref& e, ProcPtr p ); + + /** + * The reinit function reinitializes all fields. + */ + void vReinit( const Eref& e, ProcPtr p ); + + /** + * The initProc function is for a second phase of 'process' + * operations. It sends the axial and raxial messages + * to other compartments. It has to be executed out of phase + * with the main process so that all compartments are + * equivalent and there is no calling order dependence in + * the results. + */ + void vInitProc( const Eref& e, ProcPtr p ); + + /** + * Empty function to do another reinit step out of phase + * with the main one. Nothing needs doing there. + */ + void vInitReinit( const Eref& e, ProcPtr p ); + + /** + * handleChannel handles information coming from the channel + * to the compartment + */ + void vHandleChannel( const Eref& e, double Gk, double Ek); + + /** + * handleRaxial handles incoming raxial message data. + */ + void vHandleRaxial( double Ra, double Vm); + + /** + * handleAxial handles incoming axial message data. + */ + void vHandleAxial( double Vm); + + /** + * Injects a constantly updated current into the compartment. + * Unlike the 'inject' field, this injected current is + * applicable only for a single timestep. So this is meant to + * be used as the destination of a message rather than as a + * one-time assignment. + */ + void vInjectMsg( const Eref& e, double current); + + /** + * Injects a constantly updated current into the + * compartment, with a probability prob. Note that it isn't + * the current amplitude that is random, it is the presence + * or absence of the current that is probabilistic. + */ + void vRandInject( const Eref& e, double prob, double current); + + /** + * Dummy function to act as recipient of 'cable' message, + * which is just for grouping compartments. + */ + void cable(); + + + /** + * Initializes the class info. + */ + static const Cinfo* initCinfo(); + +protected: + double Vm_; + double initVm_; + double Em_; + double Cm_; + double Rm_; + double Ra_; + double Im_; + double lastIm_; + double inject_; + double A_; + double B_; + double sumInject_; + +private: + double invRm_; + double dt_; + static const double EPSILON; + }; } diff --git a/moose-core/biophysics/CompartmentBase.cpp b/moose-core/biophysics/CompartmentBase.cpp index 1528f54f6cde2ba2d9e54cb0dcf729848e357a5b..795acb5a0950666cd24ac4c9427770104f2d0ce5 100644 --- a/moose-core/biophysics/CompartmentBase.cpp +++ b/moose-core/biophysics/CompartmentBase.cpp @@ -9,7 +9,6 @@ #include "header.h" #include "ElementValueFinfo.h" -#include "../randnum/randnum.h" #include "CompartmentBase.h" #include "CompartmentDataHolder.h" #include "../shell/Wildcard.h" diff --git a/moose-core/biophysics/MarkovSolver.cpp b/moose-core/biophysics/MarkovSolver.cpp index b5e3ddbba288cd3ecfd8ada9b2f40601d444dd1c..0c87795063770e5675cb0cef6e15e0190e98fef6 100644 --- a/moose-core/biophysics/MarkovSolver.cpp +++ b/moose-core/biophysics/MarkovSolver.cpp @@ -85,7 +85,7 @@ Matrix* MarkovSolver::computePadeApproximant( Matrix* Q1, vector< unsigned int >* swaps = new vector< unsigned int >; unsigned int n = Q1->size(); unsigned int degree = mCandidates[degreeIndex]; - double *padeCoeffs; + double *padeCoeffs = NULL; Matrix *V = matAlloc(n); //Vector of Matrix pointers. Each entry is an even power of Q. diff --git a/moose-core/biophysics/Neuron.cpp b/moose-core/biophysics/Neuron.cpp index 6a5e42d390dcae427fdc6031541a51becc962d89..aa86759175fc376489128abe3f4a14d1caae32b5 100644 --- a/moose-core/biophysics/Neuron.cpp +++ b/moose-core/biophysics/Neuron.cpp @@ -105,455 +105,457 @@ const unsigned int nuParser::numVal = 13; const Cinfo* Neuron::initCinfo() { - ///////////////////////////////////////////////////////////////////// - // ValueFinfos - ///////////////////////////////////////////////////////////////////// - static ValueFinfo< Neuron, double > RM( "RM", - "Membrane resistivity, in ohm.m^2. Default value is 1.0.", - &Neuron::setRM, - &Neuron::getRM - ); - static ValueFinfo< Neuron, double > RA( "RA", - "Axial resistivity of cytoplasm, in ohm.m. Default value is 1.0.", - &Neuron::setRA, - &Neuron::getRA - ); - static ValueFinfo< Neuron, double > CM( "CM", - "Membrane Capacitance, in F/m^2. Default value is 0.01", - &Neuron::setCM, - &Neuron::getCM - ); - static ValueFinfo< Neuron, double > Em( "Em", - "Resting membrane potential of compartments, in Volts. " - "Default value is -0.065.", - &Neuron::setEm, - &Neuron::getEm - ); - static ValueFinfo< Neuron, double > theta( "theta", - "Angle to rotate cell geometry, around long axis of neuron. " - "Think Longitude. Units are radians. " - "Default value is zero, which means no rotation. ", - &Neuron::setTheta, - &Neuron::getTheta - ); - static ValueFinfo< Neuron, double > phi( "phi", - "Angle to rotate cell geometry, around elevation of neuron. " - "Think Latitude. Units are radians. " - "Default value is zero, which means no rotation. ", - &Neuron::setPhi, - &Neuron::getPhi - ); - - static ValueFinfo< Neuron, string > sourceFile( "sourceFile", - "Name of source file from which to load a model. " - "Accepts swc and dotp formats at present. " - "Both these formats require that the appropriate channel " - "definitions should have been loaded into /library. ", - &Neuron::setSourceFile, - &Neuron::getSourceFile - ); - - static ValueFinfo< Neuron, double > compartmentLengthInLambdas( - "compartmentLengthInLambdas", - "Units: meters (SI). \n" - "Electrotonic length to use for the largest compartment in the " - "model. Used to define subdivision of branches into compartments. " - "For example, if we set *compartmentLengthInLambdas* to 0.1, " - "and *lambda* (electrotonic length) is 250 microns, then it " - "sets the compartment length to 25 microns. Thus a dendritic " - "branch of 500 microns is subdivided into 20 commpartments. " - "If the branch is shorter than *compartmentLengthInLambdas*, " - "then it is not subdivided. " - "If *compartmentLengthInLambdas* is set to 0 then the original " - "compartmental structure of the model is preserved. " - " Note that this routine does NOT merge branches, even if " - "*compartmentLengthInLambdas* is bigger than the branch. " - "While all this subdivision is being done, the Neuron class " - "preserves as detailed a geometry as it can, so it can rebuild " - "the more detailed version if needed. " - "Default value of *compartmentLengthInLambdas* is 0. ", - &Neuron::setCompartmentLengthInLambdas, - &Neuron::getCompartmentLengthInLambdas - ); - - static ElementValueFinfo< Neuron, vector< string > > - channelDistribution( - "channelDistribution", - "Specification for distribution of channels, CaConcens and " - "any other model components that are defined as prototypes and " - "have to be placed on the electrical compartments.\n" - "Arguments: proto path field expr [field expr]...\n" - " Each entry is terminated with an empty string. " - "The prototype is any object created in */library*, " - "If a channel matching the prototype name already exists, then " - "all subsequent operations are applied to the extant channel and " - "a new one is not created. " - "The paired arguments are as follows: \n" - "The *field* argument specifies the name of the parameter " - "that is to be assigned by the expression.\n" - "The *expression* argument is a mathematical expression in " - "the muparser framework, which permits most operations including " - "trig and transcendental ones. Of course it also handles simple " - "numerical values like 1.0, 1e-10 and so on. " - "Available arguments for muParser are:\n" - " p, g, L, len, dia, maxP, maxG, maxL \n" - " p: path distance from soma, measured along dendrite, in metres.\n" - " g: geometrical distance from soma, in metres.\n" - " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" - " len: length of compartment, in metres.\n" - " dia: for diameter of compartment, in metres.\n" - " maxP: Maximum value of *p* for this neuron. \n" - " maxG: Maximum value of *g* for this neuron. \n" - " maxL: Maximum value of *L* for this neuron.\n" - "The expression for the first field must evaluate to > 0 " - "for the channel to be installed. For example, for " - "channels, if Field == Gbar, and func( r, L, len, dia) < 0, \n" - "then the channel is not installed. This feature is typically " - "used with the sign() or Heaviside H() function to limit range: " - "for example: H(1 - L) will only put channels closer than " - "one length constant from the soma, and zero elsewhere. \n" - "Available fields are: \n" - "Channels: Gbar (install), Ek \n" - "CaConcen: shellDia (install), shellFrac (install), tau, min\n" - "Unless otherwise noted, all fields are scaled appropriately by " - "the dimensions of their compartment. Thus the channel " - "maximal conductance Gbar is automatically scaled by the area " - "of the compartment, and the user does not need to insert this " - "scaling into the calculations.\n" - "All parameters are expressed in SI units. Conductance, for " - "example, is Siemens/sq metre. " - "\n\n" - "Some example function forms might be for a channel Gbar: \n" - " p < 10e-6 ? 400 : 0.0 \n" - " equivalently, \n" - " H(10e-6 - p) * 400 \n" - " equivalently, \n" - " ( sign(10e-6 - p) + 1) * 200 \n" - "Each of these forms instruct the function to " - "set channel Gbar to 400 S/m^2 only within 10 microns path " - "distance of soma\n" - "\n" - " L < 1.0 ? 100 * exp( -L ) : 0.0 \n" - " ->Set channel Gbar to an exponentially falling function of " - "electrotonic distance from soma, provided L is under " - "1.0 lambdas. \n", - &Neuron::setChannelDistribution, - &Neuron::getChannelDistribution - ); - - static ElementValueFinfo< Neuron, vector< string > > - passiveDistribution( - "passiveDistribution", - "Specification for distribution of passive properties of cell.\n" - "Arguments: . path field expr [field expr]...\n" - "Note that the arguments list starts with a period. " - " Each entry is terminated with an empty string. " - "The paired arguments are as follows: \n" - "The *field* argument specifies the name of the parameter " - "that is to be assigned by the expression.\n" - "The *expression* argument is a mathematical expression in " - "the muparser framework, which permits most operations including " - "trig and transcendental ones. Of course it also handles simple " - "numerical values like 1.0, 1e-10 and so on. " - "Available arguments for muParser are:\n" - " p, g, L, len, dia, maxP, maxG, maxL \n" - " p: path distance from soma, measured along dendrite, in metres.\n" - " g: geometrical distance from soma, in metres.\n" - " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" - " len: length of compartment, in metres.\n" - " dia: for diameter of compartment, in metres.\n" - " maxP: Maximum value of *p* for this neuron. \n" - " maxG: Maximum value of *g* for this neuron. \n" - " maxL: Maximum value of *L* for this neuron.\n" - "Available fields are: \n" - "RM, RA, CM, Rm, Ra, Cm, Em, initVm \n" - "The first three fields are scaled appropriately by " - "the dimensions of their compartment. Thus the membrane " - "resistivity RM (ohms.m^2) is automatically scaled by the area " - "of the compartment, and the user does not need to insert this " - "scaling into the calculations to compute Rm." - "Using the Rm field lets the user directly assign the " - "membrane resistance (in ohms), presumably using len and dia.\n" - "Similarly, RA (ohms.m) and CM (Farads/m^2) are specific units " - "and the actual values for each compartment are assigned by " - "scaling by length and diameter. Ra (ohms) and Cm (Farads) " - "require explicit evaluation of the expression. " - "All parameters are expressed in SI units. Conductance, for " - "example, is Siemens/sq metre.\n" - "Note that time these calculations do NOT currently include spines\n", - &Neuron::setPassiveDistribution, - &Neuron::getPassiveDistribution - ); - - static ElementValueFinfo< Neuron, vector< string > >spineDistribution( - "spineDistribution", - "Specification for distribution of spines on dendrite. \n" - "Arguments: proto path spacing expr [field expr]...\n" - " Each entry is terminated with an empty string. " - "The *prototype* is any spine object created in */library*, \n" - "The *path* is the wildcard path of compartments on which to " - "place the spine.\n" - "The *spacing* is the spacing of spines, in metres. \n" - "The *expression* argument is a mathematical expression in " - "the muparser framework, which permits most operations including " - "trig and transcendental ones. Of course it also handles simple " - "numerical values like 1.0, 1e-10 and so on. " - "The paired arguments are as follows: \n" - "The *field* argument specifies the name of the parameter " - "that is to be assigned by the expression.\n" - "The *expression* argument is a mathematical expression as above. " - "Available arguments for muParser are:\n" - " p, g, L, len, dia, maxP, maxG, maxL \n" - " p: path distance from soma, measured along dendrite, in metres.\n" - " g: geometrical distance from soma, in metres.\n" - " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" - " len: length of compartment, in metres.\n" - " dia: for diameter of compartment, in metres.\n" - " maxP: Maximum value of *p* for this neuron. \n" - " maxG: Maximum value of *g* for this neuron. \n" - " maxL: Maximum value of *L* for this neuron.\n" - "The expression for the *spacing* field must evaluate to > 0 for " - "the spine to be installed. For example, if the expresssion is\n" - " H(1 - L) \n" - "then the systemwill only put spines closer than " - "one length constant from the soma, and zero elsewhere. \n" - "Available spine parameters are: \n" - "spacing, minSpacing, size, sizeDistrib " - "angle, angleDistrib \n", - &Neuron::setSpineDistribution, - &Neuron::getSpineDistribution - ); - - - static ReadOnlyValueFinfo< Neuron, unsigned int > numCompartments( - "numCompartments", - "Number of electrical compartments in model. ", - &Neuron::getNumCompartments - ); - - static ReadOnlyValueFinfo< Neuron, unsigned int > numSpines( - "numSpines", - "Number of dendritic spines in model. ", - &Neuron::getNumSpines - ); - - static ReadOnlyValueFinfo< Neuron, unsigned int > numBranches( - "numBranches", - "Number of branches in dendrites. ", - &Neuron::getNumBranches - ); - - static ReadOnlyValueFinfo< Neuron, vector< double > > pathDistFromSoma( - "pathDistanceFromSoma", - "geometrical path distance of each segment from soma, measured by " - "threading along the dendrite.", - &Neuron::getPathDistFromSoma - ); - - static ReadOnlyValueFinfo< Neuron, vector< double > > geomDistFromSoma( - "geometricalDistanceFromSoma", - "geometrical distance of each segment from soma.", - &Neuron::getGeomDistFromSoma - ); - - static ReadOnlyValueFinfo< Neuron, vector< double > > elecDistFromSoma( - "electrotonicDistanceFromSoma", - "geometrical distance of each segment from soma, as measured along " - "the dendrite.", - &Neuron::getElecDistFromSoma - ); - static ReadOnlyValueFinfo< Neuron, vector< ObjId > > compartments( - "compartments", - "Vector of ObjIds of electrical compartments. Order matches order " - "of segments, and also matches the order of the electrotonic and " - "geometricalDistanceFromSoma vectors. ", - &Neuron::getCompartments - ); - - static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< ObjId > > - compartmentsFromExpression( - "compartmentsFromExpression", - "Vector of ObjIds of electrical compartments that match the " - "'path expression' pair in the argument string.", - &Neuron::getExprElist - ); - - static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< double > > - valuesFromExpression( - "valuesFromExpression", - "Vector of values computed for each electrical compartment that " - "matches the 'path expression' pair in the argument string." - "This has 13 times the number of entries as # of compartments." - "For each compartment the entries are: \n" - "val, p, g, L, len, dia, maxP, maxG, maxL, x, y, z, 0", - &Neuron::getExprVal - ); - - static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< ObjId > > - spinesFromExpression( - "spinesFromExpression", - //"Vector of ObjIds of spines/heads sitting on the electrical " - //"compartments that match the 'path expression' pair in the " - //"argument string.", - "Vector of ObjIds of compartments comprising spines/heads " - "that match the 'path expression' pair in the " - "argument string.", - &Neuron::getSpinesFromExpression - ); - - static ReadOnlyLookupElementValueFinfo< Neuron, ObjId,vector< ObjId > > - spinesOnCompartment( - "spinesOnCompartment", - "Vector of ObjIds of spines shafts/heads sitting on the specified " - "electrical compartment. If each spine has a shaft and a head," - "and there are 10 spines on the compartment, there will be 20 " - "entries in the returned vector, ordered " - "shaft0, head0, shaft1, head1, ... ", - &Neuron::getSpinesOnCompartment - ); - - static ReadOnlyLookupElementValueFinfo< Neuron, ObjId, ObjId > - parentCompartmentOfSpine( - "parentCompartmentOfSpine", - "Returns parent compartment of specified spine compartment." - "Both the spine head or its shaft will return the same parent.", - &Neuron::getParentCompartmentOfSpine - ); - - static ReadOnlyLookupElementValueFinfo< Neuron, vector< ObjId >, vector< ObjId > > - spineIdsFromCompartmentIds( - "spineIdsFromCompartmentIds", - "Vector of ObjIds of spine entries (FieldElements on this Neuron, " - "used for scaling) that map to the the specified " - "electrical compartments. If a bad compartment Id is given, the" - "corresponding spine entry is the root Id.", - &Neuron::getSpineIdsFromCompartmentIds - ); - - ///////////////////////////////////////////////////////////////////// - // DestFinfos - ///////////////////////////////////////////////////////////////////// - static DestFinfo buildSegmentTree( "buildSegmentTree", - "Build the reference segment tree structure using the child " - "compartments of the current Neuron. Fills in all the coords and " - "length constant information into the segments, for later use " - "when we build reduced compartment trees and channel " - "distributions. Should only be called once, since subsequent use " - "on a reduced model will lose the original full cell geometry. ", - new EpFunc0< Neuron >( &Neuron::buildSegmentTree ) - ); - static DestFinfo setSpineAndPsdMesh( "setSpineAndPsdMesh", - "Assigns the spine and psd mesh to the Neuron. This is used " - "to build up a mapping from Spine entries on the Neuron to " - "chem spines and PSDs, so that volume change operations from " - "the Spine can propagate to the chem systems.", - new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdMesh ) - ); - static DestFinfo setSpineAndPsdDsolve( "setSpineAndPsdDsolve", - "Assigns the Dsolves used by spine and PSD to the Neuron. " - "This is used " - "to handle the rescaling of diffusion rates when spines are " - "resized. ", - new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdDsolve ) - ); - - /* - static DestFinfo rotateInSpace( "rotateInSpace", - theta, phi - static DestFinfo transformInSpace( "transformInSpace", - transfMatrix(4x4) - static DestFinfo saveAsNeuroML( "saveAsNeuroML", fname ) - static DestFinfo saveAsDotP( "saveAsDotP", fname ) - static DestFinfo saveAsSwc( "saveAsSwc", fname ) - */ - ///////////////////////////////////////////////////////////////////// - // FieldElement - ///////////////////////////////////////////////////////////////////// - static FieldElementFinfo< Neuron, Spine > spineFinfo( - "spine", - "Field Element for spines. Used to handle dynamic " - "geometry changes in spines. ", - Spine::initCinfo(), - &Neuron::lookupSpine, - &Neuron::setNumSpines, - &Neuron::getNumSpines, - false - ); - - ///////////////////////////////////////////////////////////////////// - static Finfo* neuronFinfos[] = - { - &RM, // ValueFinfo - &RA, // ValueFinfo - &CM, // ValueFinfo - &Em, // ValueFinfo - &theta, // ValueFinfo - &phi, // ValueFinfo - &sourceFile, // ValueFinfo - &compartmentLengthInLambdas, // ValueFinfo - &numCompartments, // ReadOnlyValueFinfo - &numSpines, // ReadOnlyValueFinfo - &numBranches, // ReadOnlyValueFinfo - &pathDistFromSoma, // ReadOnlyValueFinfo - &geomDistFromSoma, // ReadOnlyValueFinfo - &elecDistFromSoma, // ReadOnlyValueFinfo - &compartments, // ReadOnlyValueFinfo - &channelDistribution, // ValueFinfo - &passiveDistribution, // ValueFinfo - &spineDistribution, // ValueFinfo - // &mechSpec, // ValueFinfo - // &spineSpecification, // ValueFinfo - &compartmentsFromExpression, // ReadOnlyLookupValueFinfo - &valuesFromExpression, // ReadOnlyLookupValueFinfo - &spinesFromExpression, // ReadOnlyLookupValueFinfo - &spinesOnCompartment, // ReadOnlyLookupValueFinfo - &parentCompartmentOfSpine, // ReadOnlyLookupValueFinfo - &spineIdsFromCompartmentIds, // ReadOnlyLookupValueFinfo - &buildSegmentTree, // DestFinfo - &setSpineAndPsdMesh, // DestFinfo - &setSpineAndPsdDsolve, // DestFinfo - &spineFinfo, // FieldElementFinfo - }; - static string doc[] = - { - "Name", "Neuron", - "Author", "C H Chaitanya, Upi Bhalla", - "Description", "Neuron - Manager for neurons. " - "Handles high-level specification of distribution of " - "spines, channels and passive properties. Also manages " - "spine resizing through a Spine FieldElement. ", - }; - static Dinfo<Neuron> dinfo; - static Cinfo neuronCinfo( - "Neuron", - Neutral::initCinfo(), - neuronFinfos, sizeof( neuronFinfos ) / sizeof( Finfo* ), - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); - - return &neuronCinfo; + ///////////////////////////////////////////////////////////////////// + // ValueFinfos + ///////////////////////////////////////////////////////////////////// + static ValueFinfo< Neuron, double > RM( "RM", + "Membrane resistivity, in ohm.m^2. Default value is 1.0.", + &Neuron::setRM, + &Neuron::getRM + ); + static ValueFinfo< Neuron, double > RA( "RA", + "Axial resistivity of cytoplasm, in ohm.m. Default value is 1.0.", + &Neuron::setRA, + &Neuron::getRA + ); + static ValueFinfo< Neuron, double > CM( "CM", + "Membrane Capacitance, in F/m^2. Default value is 0.01", + &Neuron::setCM, + &Neuron::getCM + ); + static ValueFinfo< Neuron, double > Em( "Em", + "Resting membrane potential of compartments, in Volts. " + "Default value is -0.065.", + &Neuron::setEm, + &Neuron::getEm + ); + static ValueFinfo< Neuron, double > theta( "theta", + "Angle to rotate cell geometry, around long axis of neuron. " + "Think Longitude. Units are radians. " + "Default value is zero, which means no rotation. ", + &Neuron::setTheta, + &Neuron::getTheta + ); + static ValueFinfo< Neuron, double > phi( "phi", + "Angle to rotate cell geometry, around elevation of neuron. " + "Think Latitude. Units are radians. " + "Default value is zero, which means no rotation. ", + &Neuron::setPhi, + &Neuron::getPhi + ); + + static ValueFinfo< Neuron, string > sourceFile( "sourceFile", + "Name of source file from which to load a model. " + "Accepts swc and dotp formats at present. " + "Both these formats require that the appropriate channel " + "definitions should have been loaded into /library. ", + &Neuron::setSourceFile, + &Neuron::getSourceFile + ); + + static ValueFinfo< Neuron, double > compartmentLengthInLambdas( + "compartmentLengthInLambdas", + "Units: meters (SI). \n" + "Electrotonic length to use for the largest compartment in the " + "model. Used to define subdivision of branches into compartments. " + "For example, if we set *compartmentLengthInLambdas* to 0.1, " + "and *lambda* (electrotonic length) is 250 microns, then it " + "sets the compartment length to 25 microns. Thus a dendritic " + "branch of 500 microns is subdivided into 20 commpartments. " + "If the branch is shorter than *compartmentLengthInLambdas*, " + "then it is not subdivided. " + "If *compartmentLengthInLambdas* is set to 0 then the original " + "compartmental structure of the model is preserved. " + " Note that this routine does NOT merge branches, even if " + "*compartmentLengthInLambdas* is bigger than the branch. " + "While all this subdivision is being done, the Neuron class " + "preserves as detailed a geometry as it can, so it can rebuild " + "the more detailed version if needed. " + "Default value of *compartmentLengthInLambdas* is 0. ", + &Neuron::setCompartmentLengthInLambdas, + &Neuron::getCompartmentLengthInLambdas + ); + + static ElementValueFinfo< Neuron, vector< string > > + channelDistribution( + "channelDistribution", + "Specification for distribution of channels, CaConcens and " + "any other model components that are defined as prototypes and " + "have to be placed on the electrical compartments.\n" + "Arguments: proto path field expr [field expr]...\n" + " Each entry is terminated with an empty string. " + "The prototype is any object created in */library*, " + "If a channel matching the prototype name already exists, then " + "all subsequent operations are applied to the extant channel and " + "a new one is not created. " + "The paired arguments are as follows: \n" + "The *field* argument specifies the name of the parameter " + "that is to be assigned by the expression.\n" + "The *expression* argument is a mathematical expression in " + "the muparser framework, which permits most operations including " + "trig and transcendental ones. Of course it also handles simple " + "numerical values like 1.0, 1e-10 and so on. " + "Available arguments for muParser are:\n" + " p, g, L, len, dia, maxP, maxG, maxL \n" + " p: path distance from soma, measured along dendrite, in metres.\n" + " g: geometrical distance from soma, in metres.\n" + " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" + " len: length of compartment, in metres.\n" + " dia: for diameter of compartment, in metres.\n" + " maxP: Maximum value of *p* for this neuron. \n" + " maxG: Maximum value of *g* for this neuron. \n" + " maxL: Maximum value of *L* for this neuron.\n" + "The expression for the first field must evaluate to > 0 " + "for the channel to be installed. For example, for " + "channels, if Field == Gbar, and func( r, L, len, dia) < 0, \n" + "then the channel is not installed. This feature is typically " + "used with the sign() or Heaviside H() function to limit range: " + "for example: H(1 - L) will only put channels closer than " + "one length constant from the soma, and zero elsewhere. \n" + "Available fields are: \n" + "Channels: Gbar (install), Ek \n" + "CaConcen: shellDia (install), shellFrac (install), tau, min\n" + "Unless otherwise noted, all fields are scaled appropriately by " + "the dimensions of their compartment. Thus the channel " + "maximal conductance Gbar is automatically scaled by the area " + "of the compartment, and the user does not need to insert this " + "scaling into the calculations.\n" + "All parameters are expressed in SI units. Conductance, for " + "example, is Siemens/sq metre. " + "\n\n" + "Some example function forms might be for a channel Gbar: \n" + " p < 10e-6 ? 400 : 0.0 \n" + " equivalently, \n" + " H(10e-6 - p) * 400 \n" + " equivalently, \n" + " ( sign(10e-6 - p) + 1) * 200 \n" + "Each of these forms instruct the function to " + "set channel Gbar to 400 S/m^2 only within 10 microns path " + "distance of soma\n" + "\n" + " L < 1.0 ? 100 * exp( -L ) : 0.0 \n" + " ->Set channel Gbar to an exponentially falling function of " + "electrotonic distance from soma, provided L is under " + "1.0 lambdas. \n", + &Neuron::setChannelDistribution, + &Neuron::getChannelDistribution + ); + + static ElementValueFinfo< Neuron, vector< string > > + passiveDistribution( + "passiveDistribution", + "Specification for distribution of passive properties of cell.\n" + "Arguments: . path field expr [field expr]...\n" + "Note that the arguments list starts with a period. " + " Each entry is terminated with an empty string. " + "The paired arguments are as follows: \n" + "The *field* argument specifies the name of the parameter " + "that is to be assigned by the expression.\n" + "The *expression* argument is a mathematical expression in " + "the muparser framework, which permits most operations including " + "trig and transcendental ones. Of course it also handles simple " + "numerical values like 1.0, 1e-10 and so on. " + "Available arguments for muParser are:\n" + " p, g, L, len, dia, maxP, maxG, maxL \n" + " p: path distance from soma, measured along dendrite, in metres.\n" + " g: geometrical distance from soma, in metres.\n" + " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" + " len: length of compartment, in metres.\n" + " dia: for diameter of compartment, in metres.\n" + " maxP: Maximum value of *p* for this neuron. \n" + " maxG: Maximum value of *g* for this neuron. \n" + " maxL: Maximum value of *L* for this neuron.\n" + "Available fields are: \n" + "RM, RA, CM, Rm, Ra, Cm, Em, initVm \n" + "The first three fields are scaled appropriately by " + "the dimensions of their compartment. Thus the membrane " + "resistivity RM (ohms.m^2) is automatically scaled by the area " + "of the compartment, and the user does not need to insert this " + "scaling into the calculations to compute Rm." + "Using the Rm field lets the user directly assign the " + "membrane resistance (in ohms), presumably using len and dia.\n" + "Similarly, RA (ohms.m) and CM (Farads/m^2) are specific units " + "and the actual values for each compartment are assigned by " + "scaling by length and diameter. Ra (ohms) and Cm (Farads) " + "require explicit evaluation of the expression. " + "All parameters are expressed in SI units. Conductance, for " + "example, is Siemens/sq metre.\n" + "Note that time these calculations do NOT currently include spines\n", + &Neuron::setPassiveDistribution, + &Neuron::getPassiveDistribution + ); + + static ElementValueFinfo< Neuron, vector< string > >spineDistribution( + "spineDistribution", + "Specification for distribution of spines on dendrite. \n" + "Arguments: proto path spacing expr [field expr]...\n" + " Each entry is terminated with an empty string. " + "The *prototype* is any spine object created in */library*, \n" + "The *path* is the wildcard path of compartments on which to " + "place the spine.\n" + "The *spacing* is the spacing of spines, in metres. \n" + "The *expression* argument is a mathematical expression in " + "the muparser framework, which permits most operations including " + "trig and transcendental ones. Of course it also handles simple " + "numerical values like 1.0, 1e-10 and so on. " + "The paired arguments are as follows: \n" + "The *field* argument specifies the name of the parameter " + "that is to be assigned by the expression.\n" + "The *expression* argument is a mathematical expression as above. " + "Available arguments for muParser are:\n" + " p, g, L, len, dia, maxP, maxG, maxL \n" + " p: path distance from soma, measured along dendrite, in metres.\n" + " g: geometrical distance from soma, in metres.\n" + " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" + " len: length of compartment, in metres.\n" + " dia: for diameter of compartment, in metres.\n" + " maxP: Maximum value of *p* for this neuron. \n" + " maxG: Maximum value of *g* for this neuron. \n" + " maxL: Maximum value of *L* for this neuron.\n" + "The expression for the *spacing* field must evaluate to > 0 for " + "the spine to be installed. For example, if the expresssion is\n" + " H(1 - L) \n" + "then the systemwill only put spines closer than " + "one length constant from the soma, and zero elsewhere. \n" + "Available spine parameters are: \n" + "spacing, minSpacing, size, sizeDistrib " + "angle, angleDistrib \n", + &Neuron::setSpineDistribution, + &Neuron::getSpineDistribution + ); + + + static ReadOnlyValueFinfo< Neuron, unsigned int > numCompartments( + "numCompartments", + "Number of electrical compartments in model. ", + &Neuron::getNumCompartments + ); + + static ReadOnlyValueFinfo< Neuron, unsigned int > numSpines( + "numSpines", + "Number of dendritic spines in model. ", + &Neuron::getNumSpines + ); + + static ReadOnlyValueFinfo< Neuron, unsigned int > numBranches( + "numBranches", + "Number of branches in dendrites. ", + &Neuron::getNumBranches + ); + + static ReadOnlyValueFinfo< Neuron, vector< double > > pathDistFromSoma( + "pathDistanceFromSoma", + "geometrical path distance of each segment from soma, measured by " + "threading along the dendrite.", + &Neuron::getPathDistFromSoma + ); + + static ReadOnlyValueFinfo< Neuron, vector< double > > geomDistFromSoma( + "geometricalDistanceFromSoma", + "geometrical distance of each segment from soma.", + &Neuron::getGeomDistFromSoma + ); + + static ReadOnlyValueFinfo< Neuron, vector< double > > elecDistFromSoma( + "electrotonicDistanceFromSoma", + "geometrical distance of each segment from soma, as measured along " + "the dendrite.", + &Neuron::getElecDistFromSoma + ); + static ReadOnlyValueFinfo< Neuron, vector< ObjId > > compartments( + "compartments", + "Vector of ObjIds of electrical compartments. Order matches order " + "of segments, and also matches the order of the electrotonic and " + "geometricalDistanceFromSoma vectors. ", + &Neuron::getCompartments + ); + + static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< ObjId > > + compartmentsFromExpression( + "compartmentsFromExpression", + "Vector of ObjIds of electrical compartments that match the " + "'path expression' pair in the argument string.", + &Neuron::getExprElist + ); + + static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< double > > + valuesFromExpression( + "valuesFromExpression", + "Vector of values computed for each electrical compartment that " + "matches the 'path expression' pair in the argument string." + "This has 13 times the number of entries as # of compartments." + "For each compartment the entries are: \n" + "val, p, g, L, len, dia, maxP, maxG, maxL, x, y, z, 0", + &Neuron::getExprVal + ); + + static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< ObjId > > + spinesFromExpression( + "spinesFromExpression", + //"Vector of ObjIds of spines/heads sitting on the electrical " + //"compartments that match the 'path expression' pair in the " + //"argument string.", + "Vector of ObjIds of compartments comprising spines/heads " + "that match the 'path expression' pair in the " + "argument string.", + &Neuron::getSpinesFromExpression + ); + + static ReadOnlyLookupElementValueFinfo< Neuron, ObjId,vector< ObjId > > + spinesOnCompartment( + "spinesOnCompartment", + "Vector of ObjIds of spines shafts/heads sitting on the specified " + "electrical compartment. If each spine has a shaft and a head," + "and there are 10 spines on the compartment, there will be 20 " + "entries in the returned vector, ordered " + "shaft0, head0, shaft1, head1, ... ", + &Neuron::getSpinesOnCompartment + ); + + static ReadOnlyLookupElementValueFinfo< Neuron, ObjId, ObjId > + parentCompartmentOfSpine( + "parentCompartmentOfSpine", + "Returns parent compartment of specified spine compartment." + "Both the spine head or its shaft will return the same parent.", + &Neuron::getParentCompartmentOfSpine + ); + + static ReadOnlyLookupElementValueFinfo< Neuron, vector< ObjId >, vector< ObjId > > + spineIdsFromCompartmentIds( + "spineIdsFromCompartmentIds", + "Vector of ObjIds of spine entries (FieldElements on this Neuron, " + "used for scaling) that map to the the specified " + "electrical compartments. If a bad compartment Id is given, the" + "corresponding spine entry is the root Id.", + &Neuron::getSpineIdsFromCompartmentIds + ); + + ///////////////////////////////////////////////////////////////////// + // DestFinfos + ///////////////////////////////////////////////////////////////////// + static DestFinfo buildSegmentTree( "buildSegmentTree", + "Build the reference segment tree structure using the child " + "compartments of the current Neuron. Fills in all the coords and " + "length constant information into the segments, for later use " + "when we build reduced compartment trees and channel " + "distributions. Should only be called once, since subsequent use " + "on a reduced model will lose the original full cell geometry. ", + new EpFunc0< Neuron >( &Neuron::buildSegmentTree ) + ); + static DestFinfo setSpineAndPsdMesh( "setSpineAndPsdMesh", + "Assigns the spine and psd mesh to the Neuron. This is used " + "to build up a mapping from Spine entries on the Neuron to " + "chem spines and PSDs, so that volume change operations from " + "the Spine can propagate to the chem systems.", + new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdMesh ) + ); + static DestFinfo setSpineAndPsdDsolve( "setSpineAndPsdDsolve", + "Assigns the Dsolves used by spine and PSD to the Neuron. " + "This is used " + "to handle the rescaling of diffusion rates when spines are " + "resized. ", + new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdDsolve ) + ); + + /* + static DestFinfo rotateInSpace( "rotateInSpace", + theta, phi + static DestFinfo transformInSpace( "transformInSpace", + transfMatrix(4x4) + static DestFinfo saveAsNeuroML( "saveAsNeuroML", fname ) + static DestFinfo saveAsDotP( "saveAsDotP", fname ) + static DestFinfo saveAsSwc( "saveAsSwc", fname ) + */ + ///////////////////////////////////////////////////////////////////// + // FieldElement + ///////////////////////////////////////////////////////////////////// + static FieldElementFinfo< Neuron, Spine > spineFinfo( + "spine", + "Field Element for spines. Used to handle dynamic " + "geometry changes in spines. ", + Spine::initCinfo(), + &Neuron::lookupSpine, + &Neuron::setNumSpines, + &Neuron::getNumSpines, + false + ); + + ///////////////////////////////////////////////////////////////////// + static Finfo* neuronFinfos[] = + { + &RM, // ValueFinfo + &RA, // ValueFinfo + &CM, // ValueFinfo + &Em, // ValueFinfo + &theta, // ValueFinfo + &phi, // ValueFinfo + &sourceFile, // ValueFinfo + &compartmentLengthInLambdas, // ValueFinfo + &numCompartments, // ReadOnlyValueFinfo + &numSpines, // ReadOnlyValueFinfo + &numBranches, // ReadOnlyValueFinfo + &pathDistFromSoma, // ReadOnlyValueFinfo + &geomDistFromSoma, // ReadOnlyValueFinfo + &elecDistFromSoma, // ReadOnlyValueFinfo + &compartments, // ReadOnlyValueFinfo + &channelDistribution, // ValueFinfo + &passiveDistribution, // ValueFinfo + &spineDistribution, // ValueFinfo + // &mechSpec, // ValueFinfo + // &spineSpecification, // ValueFinfo + &compartmentsFromExpression, // ReadOnlyLookupValueFinfo + &valuesFromExpression, // ReadOnlyLookupValueFinfo + &spinesFromExpression, // ReadOnlyLookupValueFinfo + &spinesOnCompartment, // ReadOnlyLookupValueFinfo + &parentCompartmentOfSpine, // ReadOnlyLookupValueFinfo + &spineIdsFromCompartmentIds, // ReadOnlyLookupValueFinfo + &buildSegmentTree, // DestFinfo + &setSpineAndPsdMesh, // DestFinfo + &setSpineAndPsdDsolve, // DestFinfo + &spineFinfo, // FieldElementFinfo + }; + static string doc[] = + { + "Name", "Neuron", + "Author", "C H Chaitanya, Upi Bhalla", + "Description", "Neuron - Manager for neurons. " + "Handles high-level specification of distribution of " + "spines, channels and passive properties. Also manages " + "spine resizing through a Spine FieldElement. ", + }; + static Dinfo<Neuron> dinfo; + static Cinfo neuronCinfo( + "Neuron", + Neutral::initCinfo(), + neuronFinfos, sizeof( neuronFinfos ) / sizeof( Finfo* ), + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); + + return &neuronCinfo; } static const Cinfo* neuronCinfo = Neuron::initCinfo(); //////////////////////////////////////////////////////////////////////// Neuron::Neuron() - : - RM_( 1.0 ), - RA_( 1.0 ), - CM_( 0.01 ), - Em_( -0.065 ), - theta_( 0.0 ), - phi_( 0.0 ), - maxP_( 0.0 ), - maxG_( 0.0 ), - maxL_( 0.0 ), - sourceFile_( "" ), - compartmentLengthInLambdas_( 0.2 ), - spineEntry_( this ) -{;} + : + RM_( 1.0 ), + RA_( 1.0 ), + CM_( 0.01 ), + Em_( -0.065 ), + theta_( 0.0 ), + phi_( 0.0 ), + maxP_( 0.0 ), + maxG_( 0.0 ), + maxL_( 0.0 ), + sourceFile_( "" ), + compartmentLengthInLambdas_( 0.2 ), + spineEntry_( this ) +{ + ; +} // When copying Neuron, we next have to rerun buildSegmentTree() and // setSpineAndPsdMesh @@ -633,7 +635,7 @@ static void doClassSpecificMessaging( Shell* shell, Id obj, ObjId compt ) { // cout << "Added Ca Msg for " << obj.path() << ", name = " << obj.element()->getName() << endl; ObjId mid = shell->doAddMsg( - "single", obj, "IkOut", elist[0], "current" ); + "single", obj, "IkOut", elist[0], "current" ); assert( !mid.bad()); } } @@ -988,122 +990,133 @@ vector< ObjId > Neuron::getExprElist( const Eref& e, string line ) const */ vector< double > Neuron::getExprVal( const Eref& e, string line ) const { - Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); - vector< ObjId > elist; - vector< double > val; - unsigned long pos = line.find_first_of( " \t" ); - string path = line.substr( 0, pos ); - string expr = line.substr( pos ); - ObjId oldCwe = shell->getCwe(); - shell->setCwe( e.objId() ); - wildcardFind( path, elist ); - shell->setCwe( oldCwe ); - if ( elist.size() == 0 ) - return val; - evalExprForElist( elist, expr, val ); - return val; + Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); + vector< ObjId > elist; + vector< double > val; + unsigned long pos = line.find_first_of( " \t" ); + string path = line.substr( 0, pos ); + string expr = line.substr( pos ); + ObjId oldCwe = shell->getCwe(); + shell->setCwe( e.objId() ); + wildcardFind( path, elist ); + shell->setCwe( oldCwe ); + if ( elist.size() == 0 ) + return val; + evalExprForElist( elist, expr, val ); + return val; } vector< ObjId > Neuron::getSpinesFromExpression( - const Eref& e, string line ) const -{ - unsigned long pos = line.find_first_of( " \t" ); - string path = line.substr( 0, pos ); - string expr = line.substr( pos ); - - // Look for all compartments that fit the expression. - vector< ObjId > temp = getExprElist( e, "# " + expr ); - // indexed by segIndex, includes all compts in all spines. - /* - vector< vector< Id > > allSpinesPerCompt( segId_.size() ); - for ( unsigned int i = 0; i < spines_.size(); ++i ) { - assert( allSpinesPerCompt.size() > spineParentSegIndex_[i] ); - vector< Id >& s = allSpinesPerCompt[ spineParentSegIndex_[i] ]; - s.insert( s.end(), spines_[i].begin(), spines_[i].end() ); - } - */ - vector< ObjId >ret; - if ( allSpinesPerCompt_.size() == 0 ) - return ret; - for ( vector< ObjId >::iterator - i = temp.begin(); i != temp.end(); ++i ) { - map< Id, unsigned int >::const_iterator si = - segIndex_.find( i->id ); - assert( si != segIndex_.end() ); - assert( si->second < segId_.size() ); - if ( allSpinesPerCompt_.size() > si->second ) { - const vector< Id >& s = allSpinesPerCompt_[ si->second ]; - for ( vector< Id >::const_iterator j = s.begin(); j != s.end(); ++j ){ - if ( matchBeforeBrace( *j, path ) ) - ret.push_back( *j ); - } - } - } - return ret; + const Eref& e, string line ) const +{ + unsigned long pos = line.find_first_of( " \t" ); + string path = line.substr( 0, pos ); + string expr = line.substr( pos ); + + // Look for all compartments that fit the expression. + vector< ObjId > temp = getExprElist( e, "# " + expr ); + // indexed by segIndex, includes all compts in all spines. + /* + vector< vector< Id > > allSpinesPerCompt( segId_.size() ); + for ( unsigned int i = 0; i < spines_.size(); ++i ) { + assert( allSpinesPerCompt.size() > spineParentSegIndex_[i] ); + vector< Id >& s = allSpinesPerCompt[ spineParentSegIndex_[i] ]; + s.insert( s.end(), spines_[i].begin(), spines_[i].end() ); + } + */ + vector< ObjId >ret; + if ( allSpinesPerCompt_.size() == 0 ) + return ret; + for ( vector< ObjId >::iterator + i = temp.begin(); i != temp.end(); ++i ) + { + map< Id, unsigned int >::const_iterator si = + segIndex_.find( i->id ); + assert( si != segIndex_.end() ); + assert( si->second < segId_.size() ); + if ( allSpinesPerCompt_.size() > si->second ) + { + const vector< Id >& s = allSpinesPerCompt_[ si->second ]; + for ( vector< Id >::const_iterator j = s.begin(); j != s.end(); ++j ) + { + if ( matchBeforeBrace( *j, path ) ) + ret.push_back( *j ); + } + } + } + return ret; } vector< ObjId > Neuron::getSpinesOnCompartment( - const Eref& e, ObjId compt ) const -{ - vector< ObjId > ret; - map< Id, unsigned int >::const_iterator pos = - segIndex_.find( compt.id ); - if ( pos != segIndex_.end() ) { - assert( pos->second < allSpinesPerCompt_.size() ); - const vector< Id >& spines = allSpinesPerCompt_[pos->second]; - for ( unsigned int i = 0; i < spines.size(); ++i ) - ret.push_back( spines[i] ); - } - return ret; + const Eref& e, ObjId compt ) const +{ + vector< ObjId > ret; + map< Id, unsigned int >::const_iterator pos = + segIndex_.find( compt.id ); + if ( pos != segIndex_.end() ) + { + assert( pos->second < allSpinesPerCompt_.size() ); + const vector< Id >& spines = allSpinesPerCompt_[pos->second]; + for ( unsigned int i = 0; i < spines.size(); ++i ) + ret.push_back( spines[i] ); + } + return ret; } ObjId Neuron::getParentCompartmentOfSpine( - const Eref& e, ObjId compt ) const + const Eref& e, ObjId compt ) const { - for ( unsigned int comptIndex = 0; comptIndex < allSpinesPerCompt_.size(); ++comptIndex ) { - const vector< Id >& v = allSpinesPerCompt_[comptIndex]; - for ( unsigned int j = 0; j < v.size(); j++ ) - if ( v[j] == compt.id ) - return segId_[ comptIndex ]; - } - return ObjId(); + for ( unsigned int comptIndex = 0; comptIndex < allSpinesPerCompt_.size(); ++comptIndex ) + { + const vector< Id >& v = allSpinesPerCompt_[comptIndex]; + for ( unsigned int j = 0; j < v.size(); j++ ) + if ( v[j] == compt.id ) + return segId_[ comptIndex ]; + } + return ObjId(); } vector< ObjId > Neuron::getSpineIdsFromCompartmentIds( - const Eref& e, vector< ObjId > compt ) const -{ - vector< ObjId > ret; - map< Id, unsigned int > lookupSpine; - Id spineBase = Id( e.id().value() + 1 ); - for ( unsigned int i = 0; i < spines_.size(); ++i ) { - for ( vector< Id >::const_iterator j = spines_[i].begin(); j != spines_[i].end(); ++j ) { - lookupSpine[ *j ] = i; - } - } - // cout << "################## " << lookupSpine.size() << endl; - for ( map< Id, unsigned int >::const_iterator k = lookupSpine.begin(); k != lookupSpine.end(); ++k ) { - // cout << "spine[" << k->second << "] has " << k->first.element()->getName() << endl; - // cout << "spine[" << k->second << "] has " << k->first << endl; + const Eref& e, vector< ObjId > compt ) const +{ + vector< ObjId > ret; + map< Id, unsigned int > lookupSpine; + Id spineBase = Id( e.id().value() + 1 ); + for ( unsigned int i = 0; i < spines_.size(); ++i ) + { + for ( vector< Id >::const_iterator j = spines_[i].begin(); j != spines_[i].end(); ++j ) + { + lookupSpine[ *j ] = i; + } + } + // cout << "################## " << lookupSpine.size() << endl; + for ( map< Id, unsigned int >::const_iterator k = lookupSpine.begin(); k != lookupSpine.end(); ++k ) + { + // cout << "spine[" << k->second << "] has " << k->first.element()->getName() << endl; + // cout << "spine[" << k->second << "] has " << k->first << endl; - } - for ( vector< ObjId >::const_iterator j = compt.begin(); j != compt.end(); ++j ) - { - // cout << "compt: " << *j << " " << j->element()->getName() << endl; - map< Id, unsigned int >::const_iterator k = lookupSpine.find( j->id ); - if ( k != lookupSpine.end() ) { - ret.push_back( ObjId( spineBase, e.dataIndex(), k->second ) ); - // cout << "spine[" << k->second << "] has " << j->element()->getName() << endl; - } else { - ret.push_back( ObjId() ); - } - } - return ret; + } + for ( vector< ObjId >::const_iterator j = compt.begin(); j != compt.end(); ++j ) + { + // cout << "compt: " << *j << " " << j->element()->getName() << endl; + map< Id, unsigned int >::const_iterator k = lookupSpine.find( j->id ); + if ( k != lookupSpine.end() ) + { + ret.push_back( ObjId( spineBase, e.dataIndex(), k->second ) ); + // cout << "spine[" << k->second << "] has " << j->element()->getName() << endl; + } + else + { + ret.push_back( ObjId() ); + } + } + return ret; } void Neuron::buildElist( const Eref& e, - const vector< string >& line, - vector< ObjId >& elist, - vector< double >& val ) + const vector< string >& line, + vector< ObjId >& elist, + vector< double >& val ) { Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); const string& path = line[1]; @@ -1111,7 +1124,7 @@ void Neuron::buildElist( const Eref& e, ObjId oldCwe = shell->getCwe(); shell->setCwe( e.objId() ); wildcardFind( path, elist ); - sort( elist.begin(), elist.end() ); + sort( elist.begin(), elist.end() ); shell->setCwe( oldCwe ); evalExprForElist( elist, expr, val ); } @@ -1286,7 +1299,7 @@ static void fillSegments( vector< SwcSegment >& segs, comptType = 3; // generic dendrite } } - // cout << "Seg[" << i << "].xy = " << int(x*1e6) << " " << int(y*1e6) << endl; + // cout << "Seg[" << i << "].xy = " << int(x*1e6) << " " << int(y*1e6) << endl; segs.push_back( SwcSegment( i, comptType, x, y, z, dia/2.0, paIndex ) ); @@ -1350,7 +1363,7 @@ void Neuron::buildSegmentTree( const Eref& e ) { vector< Id > kids; Neutral::children( e, kids ); - sort( kids.begin(), kids.end() ); + sort( kids.begin(), kids.end() ); soma_ = fillSegIndex( kids, segIndex_ ); if ( kids.size() == 0 || soma_ == Id() ) @@ -1769,26 +1782,30 @@ string findArg( const vector<string>& line, const string& field ) /// Add entries into the pos vector for a given compartment i. static void addPos( unsigned int segIndex, unsigned int eIndex, - double spacing, double minSpacing, - double dendLength, - vector< unsigned int >& seglistIndex, - vector< unsigned int >& elistIndex, - vector< double >& pos ) -{ - if ( minSpacing < spacing * 0.1 && minSpacing < 1e-7 ) - minSpacing = spacing * 0.1; - if ( minSpacing > spacing * 0.5 ) - minSpacing = spacing * 0.5; - unsigned int n = 1 + dendLength / minSpacing; - double dx = dendLength / n; - for( unsigned int i = 0; i < n; ++i ) { - if ( moose::mtrand() < dx / spacing ) { - seglistIndex.push_back( segIndex ); - elistIndex.push_back( eIndex ); - pos.push_back( i * dx + dx*0.5 ); - } - } + double spacing, double minSpacing, + double dendLength, + vector< unsigned int >& seglistIndex, + vector< unsigned int >& elistIndex, + vector< double >& pos ) +{ + if ( minSpacing < spacing * 0.1 && minSpacing < 1e-7 ) + minSpacing = spacing * 0.1; + if ( minSpacing > spacing * 0.5 ) + minSpacing = spacing * 0.5; + unsigned int n = 1 + dendLength / minSpacing; + double dx = dendLength / n; + for( unsigned int i = 0; i < n; ++i ) + { + // Use global RNG. + if ( moose::mtrand() < dx / spacing ) + { + seglistIndex.push_back( segIndex ); + elistIndex.push_back( eIndex ); + pos.push_back( i * dx + dx*0.5 ); + } + } } + /* * This version tries to put in Pos using simple increments from the * start of each compt. Multiple issues including inability to put @@ -1822,169 +1839,187 @@ static void addPos( unsigned int segIndex, unsigned int eIndex, */ void Neuron::makeSpacingDistrib( const vector< ObjId >& elist, - const vector< double >& val, - vector< unsigned int >& seglistIndex, - vector< unsigned int >& elistIndex, - vector< double >& pos, - const vector< string >& line ) const -{ - string distribExpr = findArg( line, "spacingDistrib" ); - pos.resize( 0 ); - elistIndex.resize( 0 ); - - try { - nuParser parser( distribExpr ); - - for ( unsigned int i = 0; i < elist.size(); ++i ) { - unsigned int j = i * nuParser::numVal; - if ( val[ j + nuParser::EXPR ] > 0 ) { - double spacing = val[ j + nuParser::EXPR ]; - double spacingDistrib = parser.eval( val.begin() + j ); - if ( spacingDistrib > spacing || spacingDistrib < 0 ) { - cout << "Warning: Neuron::makeSpacingDistrib: " << - "0 < " << spacingDistrib << " < " << spacing << - " fails on " << elist[i].path() << ". Using 0.\n"; - spacingDistrib = 0.0; - } - map< Id, unsigned int>::const_iterator - lookupDend = segIndex_.find( elist[i] ); - if ( lookupDend != segIndex_.end() ) { - double dendLength = segs_[lookupDend->second].length(); - addPos( lookupDend->second, i, - spacing, spacingDistrib, dendLength, - seglistIndex, elistIndex, pos ); - } - } - } - } - catch ( mu::Parser::exception_type& err ) - { - cout << err.GetMsg() << endl; - } + const vector< double >& val, + vector< unsigned int >& seglistIndex, + vector< unsigned int >& elistIndex, + vector< double >& pos, + const vector< string >& line ) const +{ + string distribExpr = findArg( line, "spacingDistrib" ); + pos.resize( 0 ); + elistIndex.resize( 0 ); + + try + { + nuParser parser( distribExpr ); + + for ( unsigned int i = 0; i < elist.size(); ++i ) + { + unsigned int j = i * nuParser::numVal; + if ( val[ j + nuParser::EXPR ] > 0 ) + { + double spacing = val[ j + nuParser::EXPR ]; + double spacingDistrib = parser.eval( val.begin() + j ); + if ( spacingDistrib > spacing || spacingDistrib < 0 ) + { + cout << "Warning: Neuron::makeSpacingDistrib: " << + "0 < " << spacingDistrib << " < " << spacing << + " fails on " << elist[i].path() << ". Using 0.\n"; + spacingDistrib = 0.0; + } + map< Id, unsigned int>::const_iterator + lookupDend = segIndex_.find( elist[i] ); + if ( lookupDend != segIndex_.end() ) + { + double dendLength = segs_[lookupDend->second].length(); + addPos( lookupDend->second, i, + spacing, spacingDistrib, dendLength, + seglistIndex, elistIndex, pos ); + } + } + } + } + catch ( mu::Parser::exception_type& err ) + { + cout << err.GetMsg() << endl; + } } static void makeAngleDistrib ( const vector< ObjId >& elist, - const vector< double >& val, - vector< unsigned int >& elistIndex, - vector< double >& theta, - const vector< string >& line ) -{ - string angleExpr = findArg( line, "angle" ); - string angleDistribExpr = findArg( line, "angleDistrib" ); - // I won't bother with rotation and rotation distrb for now. - // Easy to add, but on reflection they don't make sense. - theta.clear(); - theta.resize( elistIndex.size(), 0.0 ); - - try { - nuParser angleParser( angleExpr ); - nuParser distribParser( angleDistribExpr ); - unsigned int lastIndex = ~0U; - double angle = 0; - double angleDistrib = 0; - for ( unsigned int k = 0; k < elistIndex.size(); ++k ) { - unsigned int i = elistIndex[k]; - if ( i != lastIndex ) { - lastIndex = i; - unsigned int j = i * nuParser::numVal; - angle = angleParser.eval( val.begin() + j ); - angleDistrib = distribParser.eval( val.begin() + j); - } - if ( angleDistrib > 0 ) - theta[k] = angle + ( moose::mtrand() - 0.5 ) * angleDistrib; - else - theta[k] = angle; - } - } - catch ( mu::Parser::exception_type& err ) - { - cout << err.GetMsg() << endl; - } + const vector< double >& val, + vector< unsigned int >& elistIndex, + vector< double >& theta, + const vector< string >& line ) +{ + string angleExpr = findArg( line, "angle" ); + string angleDistribExpr = findArg( line, "angleDistrib" ); + // I won't bother with rotation and rotation distrb for now. + // Easy to add, but on reflection they don't make sense. + theta.clear(); + theta.resize( elistIndex.size(), 0.0 ); + + try + { + nuParser angleParser( angleExpr ); + nuParser distribParser( angleDistribExpr ); + unsigned int lastIndex = ~0U; + double angle = 0; + double angleDistrib = 0; + for ( unsigned int k = 0; k < elistIndex.size(); ++k ) + { + unsigned int i = elistIndex[k]; + if ( i != lastIndex ) + { + lastIndex = i; + unsigned int j = i * nuParser::numVal; + angle = angleParser.eval( val.begin() + j ); + angleDistrib = distribParser.eval( val.begin() + j); + } + + // Use global RNG. + if ( angleDistrib > 0 ) + theta[k] = angle + ( moose::mtrand() - 0.5 ) * angleDistrib; + else + theta[k] = angle; + } + } + catch ( mu::Parser::exception_type& err ) + { + cout << err.GetMsg() << endl; + } } static void makeSizeDistrib ( const vector< ObjId >& elist, - const vector< double >& val, - vector< unsigned int >& elistIndex, - vector< double >& size, - const vector< string >& line ) -{ - string sizeExpr = findArg( line, "size" ); - string sizeDistribExpr = findArg( line, "sizeDistrib" ); - size.clear(); - size.resize( elistIndex.size(), 0.0 ); - - try { - nuParser sizeParser( sizeExpr ); - nuParser distribParser( sizeDistribExpr ); - unsigned int lastIndex = ~0U; - double sz = 1.0; - double sizeDistrib = 0; - for ( unsigned int k = 0; k < elistIndex.size(); ++k ) { - unsigned int i = elistIndex[k]; - if ( i != lastIndex ) { - lastIndex = i; - unsigned int j = i * nuParser::numVal; - sz = sizeParser.eval( val.begin() + j ); - sizeDistrib = distribParser.eval( val.begin() + j); - } - if ( sizeDistrib > 0 ) - size[k] = sz + ( moose::mtrand() - 0.5 ) * sizeDistrib; - else - size[k] = sz; - } - } - catch ( mu::Parser::exception_type& err ) - { - cout << err.GetMsg() << endl; - } + const vector< double >& val, + vector< unsigned int >& elistIndex, + vector< double >& size, + const vector< string >& line ) +{ + string sizeExpr = findArg( line, "size" ); + string sizeDistribExpr = findArg( line, "sizeDistrib" ); + size.clear(); + size.resize( elistIndex.size(), 0.0 ); + + try + { + nuParser sizeParser( sizeExpr ); + nuParser distribParser( sizeDistribExpr ); + unsigned int lastIndex = ~0U; + double sz = 1.0; + double sizeDistrib = 0; + for ( unsigned int k = 0; k < elistIndex.size(); ++k ) + { + unsigned int i = elistIndex[k]; + if ( i != lastIndex ) + { + lastIndex = i; + unsigned int j = i * nuParser::numVal; + sz = sizeParser.eval( val.begin() + j ); + sizeDistrib = distribParser.eval( val.begin() + j); + } + + // Use global RNG. + if ( sizeDistrib > 0 ) + size[k] = sz + ( moose::mtrand() - 0.5 ) * sizeDistrib; + else + size[k] = sz; + } + } + catch ( mu::Parser::exception_type& err ) + { + cout << err.GetMsg() << endl; + } } void Neuron::installSpines( const vector< ObjId >& elist, - const vector< double >& val, const vector< string >& line ) + const vector< double >& val, const vector< string >& line ) { - Id spineProto( "/library/spine" ); + Id spineProto( "/library/spine" ); - if ( spineProto == Id() ) { - cout << "Warning: Neuron::installSpines: Unable to find prototype spine: /library/spine\n"; - return; - } - // Look up elist index from pos index, since there may be many - // spines on each segment. - vector< unsigned int > elistIndex; - vector< double > pos; // spacing of the new spines along compt. - vector< double > theta; // Angle of spines - vector< double > size; // Size scaling of spines - pos.reserve( elist.size() ); - elistIndex.reserve( elist.size() ); - - makeSpacingDistrib( elist, val, - spineParentSegIndex_, elistIndex, pos, line); - makeAngleDistrib( elist, val, elistIndex, theta, line ); - makeSizeDistrib( elist, val, elistIndex, size, line ); - for ( unsigned int k = 0; k < spineParentSegIndex_.size(); ++k ) { - unsigned int i = spineParentSegIndex_[k]; - Vec x, y, z; - coordSystem( soma_, segId_[i], x, y, z ); - spines_.push_back( - addSpine( segId_[i], spineProto, pos[k], theta[k], - x, y, z, size[k], k ) - ); - } - spineToMeshOrdering_.clear(); - spineToMeshOrdering_.resize( spines_.size(), 0 ); - spineStoich_.clear(); - spineStoich_.resize( spines_.size() ); - psdStoich_.clear(); - psdStoich_.resize( spines_.size() ); - - /// Now fill in allSpinesPerCompt_ vector. First clear it out. - allSpinesPerCompt_.clear(); - allSpinesPerCompt_.resize(segId_.size() ); - for ( unsigned int i = 0; i < spines_.size(); ++i ) { - assert( allSpinesPerCompt_.size() > spineParentSegIndex_[i] ); - vector< Id >& s = allSpinesPerCompt_[ spineParentSegIndex_[i] ]; - s.insert( s.end(), spines_[i].begin(), spines_[i].end() ); - } + if ( spineProto == Id() ) + { + cout << "Warning: Neuron::installSpines: Unable to find prototype spine: /library/spine\n"; + return; + } + // Look up elist index from pos index, since there may be many + // spines on each segment. + vector< unsigned int > elistIndex; + vector< double > pos; // spacing of the new spines along compt. + vector< double > theta; // Angle of spines + vector< double > size; // Size scaling of spines + pos.reserve( elist.size() ); + elistIndex.reserve( elist.size() ); + + makeSpacingDistrib( elist, val, + spineParentSegIndex_, elistIndex, pos, line); + makeAngleDistrib( elist, val, elistIndex, theta, line ); + makeSizeDistrib( elist, val, elistIndex, size, line ); + for ( unsigned int k = 0; k < spineParentSegIndex_.size(); ++k ) + { + unsigned int i = spineParentSegIndex_[k]; + Vec x, y, z; + coordSystem( soma_, segId_[i], x, y, z ); + spines_.push_back( + addSpine( segId_[i], spineProto, pos[k], theta[k], + x, y, z, size[k], k ) + ); + } + spineToMeshOrdering_.clear(); + spineToMeshOrdering_.resize( spines_.size(), 0 ); + spineStoich_.clear(); + spineStoich_.resize( spines_.size() ); + psdStoich_.clear(); + psdStoich_.resize( spines_.size() ); + + /// Now fill in allSpinesPerCompt_ vector. First clear it out. + allSpinesPerCompt_.clear(); + allSpinesPerCompt_.resize(segId_.size() ); + for ( unsigned int i = 0; i < spines_.size(); ++i ) + { + assert( allSpinesPerCompt_.size() > spineParentSegIndex_[i] ); + vector< Id >& s = allSpinesPerCompt_[ spineParentSegIndex_[i] ]; + s.insert( s.end(), spines_[i].begin(), spines_[i].end() ); + } } //////////////////////////////////////////////////////////////////////// // Interface funcs for spines @@ -2021,8 +2056,8 @@ void Neuron::scaleBufAndRates( unsigned int spineNum, double lenScale, double diaScale ) const { double volScale = lenScale * diaScale * diaScale; - if ( doubleEq( volScale, 1.0 ) ) - return; + if ( doubleEq( volScale, 1.0 ) ) + return; if ( spineStoich_.size() == 0 ) // Perhaps no chem stuff in model, but user could have forgotten // to assign psd and spine meshes. @@ -2072,8 +2107,8 @@ void Neuron::scaleHeadDiffusion( unsigned int spineNum, double len, double dia) const { double vol = len * dia * dia * PI * 0.25; - // Note that the diffusion scale for the PSD uses half the length - // of the head compartment. I'm explicitly putting this in below. + // Note that the diffusion scale for the PSD uses half the length + // of the head compartment. I'm explicitly putting this in below. double diffScale = dia * dia * 0.25 * PI / (len/2.0); unsigned int meshIndex = spineToMeshOrdering_[ spineNum ]; Id headCompt = Field< Id >::get( headDsolve_, "compartment" ); diff --git a/moose-core/biophysics/Neuron.h b/moose-core/biophysics/Neuron.h index 777c5448600b2f56209dc016c951a359881e4da6..81b726581acd77110f76a5818c8e2ca0cf054b63 100644 --- a/moose-core/biophysics/Neuron.h +++ b/moose-core/biophysics/Neuron.h @@ -17,141 +17,141 @@ class Neuron { - public: - Neuron(); - Neuron( const Neuron& other ); - void setRM( double v ); - double getRM() const; - void setRA( double v ); - double getRA() const; - void setCM( double v ); - double getCM() const; - void setEm( double v ); - double getEm() const; - void setTheta( double v ); - double getTheta() const; - void setPhi( double v ); - double getPhi() const; - void setSourceFile( string v ); - string getSourceFile() const; - void setCompartmentLengthInLambdas( double v ); - double getCompartmentLengthInLambdas() const; - unsigned int getNumCompartments() const; - unsigned int getNumBranches() const; - vector< double> getPathDistFromSoma() const; - vector< double> getGeomDistFromSoma() const; - vector< double> getElecDistFromSoma() const; - vector< ObjId > getCompartments() const; - vector< ObjId > getExprElist( const Eref& e, string line ) const; - vector< double > getExprVal( const Eref& e, string line ) const; - vector< ObjId > getSpinesFromExpression( - const Eref& e, string line ) const; - vector< ObjId > getSpinesOnCompartment( - const Eref& e, ObjId compt ) const; - ObjId getParentCompartmentOfSpine( const Eref& e, ObjId compt ) - const; - vector< ObjId > getSpineIdsFromCompartmentIds( - const Eref& e, vector< ObjId > compt ) const; - void setChannelDistribution( const Eref& e, vector< string > v ); - vector< string > getChannelDistribution( const Eref& e ) const; - void setPassiveDistribution( const Eref& e, vector< string > v ); - vector< string > getPassiveDistribution( const Eref& e ) const; - void setSpineDistribution( const Eref& e, vector< string > v ); - vector< string > getSpineDistribution( const Eref& e ) const; - - void buildSegmentTree( const Eref& e ); - void setSpineAndPsdMesh( Id spineMesh, Id psdMesh ); - void setSpineAndPsdDsolve( Id spineDsolve, Id psdDsolve ); - - /////////////////////////////////////////////////////////////////// - // MechSpec set - /////////////////////////////////////////////////////////////////// - void updateSegmentLengths(); - void installSpines( const vector< ObjId >& elist, - const vector< double >& val, const vector< string >& line ); - void makeSpacingDistrib( - const vector< ObjId >& elist, const vector< double >& val, - vector< unsigned int >& seglistIndex, - vector< unsigned int >& elistIndex, - vector< double >& pos, - const vector< string >& line ) const; - void parseMechSpec( const Eref& e ); - void installMechanism( const string& name, - const vector< ObjId >& elist, const vector< double >& val, - const vector< string >& line ); - void buildElist( - const Eref& e, - const vector< string >& line, vector< ObjId >& elist, - vector< double >& val ); - - void evalExprForElist( const vector< ObjId >& elist, - const string& expn, vector< double >& val ) const; - - /////////////////////////////////////////////////////////////////// - // Interface for Spine class, used mostly in resizing spines. - /////////////////////////////////////////////////////////////////// - Spine* lookupSpine( unsigned int index ); - void setNumSpines( unsigned int num ); - unsigned int getNumSpines() const; - - const vector< Id >& spineIds( unsigned int index ) const; - void scaleBufAndRates( unsigned int spineNum, - double lenScale, double diaScale ) const; - void scaleShaftDiffusion( unsigned int spineNum, - double len, double dia) const; - void scaleHeadDiffusion( unsigned int spineNum, - double len, double dia) const; - - /** - * Initializes the class info. - */ - static const Cinfo* initCinfo(); - private: - double RM_; - double RA_; - double CM_; - double Em_; - double theta_; - double phi_; - double maxP_; // Maximum value of path dist from soma for this cell - double maxG_; // Maximum value of geom dist from soma for this cell - double maxL_; // Maximum value of elec dist from soma for this cell - Id soma_; - string sourceFile_; - double compartmentLengthInLambdas_; - vector< string > channelDistribution_; - vector< string > passiveDistribution_; - vector< string > spineDistribution_; - - /// Map to look up Seg index from Id of associated compt. - map< Id, unsigned int > segIndex_; - /// Look up seg index of parent compartment, from index of spine. - vector< unsigned int > spineParentSegIndex_; - vector< vector< Id > > spines_; /// Id of each compt in each spine. - - /// Ids of all spines on each compt, looked up by segIndex of compt. - vector< vector< Id > > allSpinesPerCompt_; - - /// Id of stoich associated with each spine. Typically all the same. - vector< Id > spineStoich_; - /// Id of stoich associated with each PSD. Typically all the same. - vector< Id > psdStoich_; - /// looks up spine/psd mesh index from FieldIndex of selected spine. - vector< unsigned int > spineToMeshOrdering_; - - Id headDsolve_; /// Id of the Dsolve for the head compt. - Id psdDsolve_; /// Id of the Dsolve for the PSD compt. - // looks up spine/psd Dsolve::DiffJunction::VoxelJunction index - //from FieldIndex of selected spine. - // Turns out this is the same as spineToMeshOrdering. - //vector< unsigned int > spineToVoxelJunctionOrdering_; - - /// Holder for spine operations. Contains pointer to current Neuron. - Spine spineEntry_; - - vector< Id > segId_; /// Id of compartment in each Seg entry, below. - vector< SwcSegment > segs_; - vector< SwcBranch > branches_; +public: + Neuron(); + Neuron( const Neuron& other ); + void setRM( double v ); + double getRM() const; + void setRA( double v ); + double getRA() const; + void setCM( double v ); + double getCM() const; + void setEm( double v ); + double getEm() const; + void setTheta( double v ); + double getTheta() const; + void setPhi( double v ); + double getPhi() const; + void setSourceFile( string v ); + string getSourceFile() const; + void setCompartmentLengthInLambdas( double v ); + double getCompartmentLengthInLambdas() const; + unsigned int getNumCompartments() const; + unsigned int getNumBranches() const; + vector< double> getPathDistFromSoma() const; + vector< double> getGeomDistFromSoma() const; + vector< double> getElecDistFromSoma() const; + vector< ObjId > getCompartments() const; + vector< ObjId > getExprElist( const Eref& e, string line ) const; + vector< double > getExprVal( const Eref& e, string line ) const; + vector< ObjId > getSpinesFromExpression( + const Eref& e, string line ) const; + vector< ObjId > getSpinesOnCompartment( + const Eref& e, ObjId compt ) const; + ObjId getParentCompartmentOfSpine( const Eref& e, ObjId compt ) + const; + vector< ObjId > getSpineIdsFromCompartmentIds( + const Eref& e, vector< ObjId > compt ) const; + void setChannelDistribution( const Eref& e, vector< string > v ); + vector< string > getChannelDistribution( const Eref& e ) const; + void setPassiveDistribution( const Eref& e, vector< string > v ); + vector< string > getPassiveDistribution( const Eref& e ) const; + void setSpineDistribution( const Eref& e, vector< string > v ); + vector< string > getSpineDistribution( const Eref& e ) const; + + void buildSegmentTree( const Eref& e ); + void setSpineAndPsdMesh( Id spineMesh, Id psdMesh ); + void setSpineAndPsdDsolve( Id spineDsolve, Id psdDsolve ); + + /////////////////////////////////////////////////////////////////// + // MechSpec set + /////////////////////////////////////////////////////////////////// + void updateSegmentLengths(); + void installSpines( const vector< ObjId >& elist, + const vector< double >& val, const vector< string >& line ); + void makeSpacingDistrib( + const vector< ObjId >& elist, const vector< double >& val, + vector< unsigned int >& seglistIndex, + vector< unsigned int >& elistIndex, + vector< double >& pos, + const vector< string >& line ) const; + void parseMechSpec( const Eref& e ); + void installMechanism( const string& name, + const vector< ObjId >& elist, const vector< double >& val, + const vector< string >& line ); + void buildElist( + const Eref& e, + const vector< string >& line, vector< ObjId >& elist, + vector< double >& val ); + + void evalExprForElist( const vector< ObjId >& elist, + const string& expn, vector< double >& val ) const; + + /////////////////////////////////////////////////////////////////// + // Interface for Spine class, used mostly in resizing spines. + /////////////////////////////////////////////////////////////////// + Spine* lookupSpine( unsigned int index ); + void setNumSpines( unsigned int num ); + unsigned int getNumSpines() const; + + const vector< Id >& spineIds( unsigned int index ) const; + void scaleBufAndRates( unsigned int spineNum, + double lenScale, double diaScale ) const; + void scaleShaftDiffusion( unsigned int spineNum, + double len, double dia) const; + void scaleHeadDiffusion( unsigned int spineNum, + double len, double dia) const; + + /** + * Initializes the class info. + */ + static const Cinfo* initCinfo(); +private: + double RM_; + double RA_; + double CM_; + double Em_; + double theta_; + double phi_; + double maxP_; // Maximum value of path dist from soma for this cell + double maxG_; // Maximum value of geom dist from soma for this cell + double maxL_; // Maximum value of elec dist from soma for this cell + Id soma_; + string sourceFile_; + double compartmentLengthInLambdas_; + vector< string > channelDistribution_; + vector< string > passiveDistribution_; + vector< string > spineDistribution_; + + /// Map to look up Seg index from Id of associated compt. + map< Id, unsigned int > segIndex_; + /// Look up seg index of parent compartment, from index of spine. + vector< unsigned int > spineParentSegIndex_; + vector< vector< Id > > spines_; /// Id of each compt in each spine. + + /// Ids of all spines on each compt, looked up by segIndex of compt. + vector< vector< Id > > allSpinesPerCompt_; + + /// Id of stoich associated with each spine. Typically all the same. + vector< Id > spineStoich_; + /// Id of stoich associated with each PSD. Typically all the same. + vector< Id > psdStoich_; + /// looks up spine/psd mesh index from FieldIndex of selected spine. + vector< unsigned int > spineToMeshOrdering_; + + Id headDsolve_; /// Id of the Dsolve for the head compt. + Id psdDsolve_; /// Id of the Dsolve for the PSD compt. + // looks up spine/psd Dsolve::DiffJunction::VoxelJunction index + //from FieldIndex of selected spine. + // Turns out this is the same as spineToMeshOrdering. + //vector< unsigned int > spineToVoxelJunctionOrdering_; + + /// Holder for spine operations. Contains pointer to current Neuron. + Spine spineEntry_; + + vector< Id > segId_; /// Id of compartment in each Seg entry, below. + vector< SwcSegment > segs_; + vector< SwcBranch > branches_; }; diff --git a/moose-core/biophysics/RandSpike.cpp b/moose-core/biophysics/RandSpike.cpp index 4678970f2f7836f99f3fb6e7bdb2710e48b3a9a4..57fdf8afe5774b08a03825298d572af0d0be3718 100644 --- a/moose-core/biophysics/RandSpike.cpp +++ b/moose-core/biophysics/RandSpike.cpp @@ -7,123 +7,127 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" -#include "../randnum/randnum.h" +#include "../basecode/header.h" +#include "../basecode/global.h" + #include "RandSpike.h" - /////////////////////////////////////////////////////// - // MsgSrc definitions - /////////////////////////////////////////////////////// -static SrcFinfo1< double > *spikeOut() { - static SrcFinfo1< double > spikeOut( "spikeOut", - "Sends out a trigger for an event."); - return &spikeOut; +/////////////////////////////////////////////////////// +// MsgSrc definitions +/////////////////////////////////////////////////////// +static SrcFinfo1< double > *spikeOut() +{ + static SrcFinfo1< double > spikeOut( "spikeOut", + "Sends out a trigger for an event."); + return &spikeOut; } const Cinfo* RandSpike::initCinfo() { - /////////////////////////////////////////////////////// - // Shared message definitions - /////////////////////////////////////////////////////// - static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< RandSpike >( &RandSpike::process ) ); - static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< RandSpike >( &RandSpike::reinit ) ); - - static Finfo* processShared[] = - { - &process, &reinit - }; - - static SharedFinfo proc( "proc", - "Shared message to receive Process message from scheduler", - processShared, sizeof( processShared ) / sizeof( Finfo* ) ); - - ////////////////////////////////////////////////////////////////// - // Dest Finfos. - ////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////// - // Value Finfos. - ////////////////////////////////////////////////////////////////// - - static ValueFinfo< RandSpike, double > rate( "rate", - "Specifies rate for random spike train. Note that this is" - "probabilistic, so the instantaneous rate may differ. " - "If the rate is assigned be message and it varies slowly then " - "the average firing rate will approach the specified rate", - &RandSpike::setRate, - &RandSpike::getRate - ); - static ValueFinfo< RandSpike, double > refractT( "refractT", - "Refractory Time.", - &RandSpike::setRefractT, - &RandSpike::getRefractT - ); - static ValueFinfo< RandSpike, double > absRefract( "abs_refract", - "Absolute refractory time. Synonym for refractT.", - &RandSpike::setRefractT, - &RandSpike::getRefractT - ); - static ValueFinfo< RandSpike, bool > doPeriodic( "doPeriodic", - "Flag: when false, do Poisson process with specified mean rate.\n" - "When true, fire periodically at specified rate.\n" - "Defaults to false. Note that refractory time overrides this: " - "Rate cannot exceed 1/refractT.", - &RandSpike::setDoPeriodic, - &RandSpike::getDoPeriodic - ); - static ReadOnlyValueFinfo< RandSpike, bool > hasFired( "hasFired", - "True if RandSpike has just fired", - &RandSpike::getFired - ); - - static Finfo* spikeGenFinfos[] = - { - spikeOut(), // SrcFinfo - &proc, // Shared - &rate, // Value - &refractT, // Value - &absRefract, // Value - &doPeriodic, // Value - &hasFired, // ReadOnlyValue - }; - - static string doc[] = - { - "Name", "RandSpike", - "Author", "Upi Bhalla", - "Description", "RandSpike object, generates random or regular " - "spikes at " - "specified mean rate. Based closely on GENESIS randspike. " - }; - static Dinfo< RandSpike > dinfo; - static Cinfo spikeGenCinfo( - "RandSpike", - Neutral::initCinfo(), - spikeGenFinfos, sizeof( spikeGenFinfos ) / sizeof( Finfo* ), - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); - - return &spikeGenCinfo; + /////////////////////////////////////////////////////// + // Shared message definitions + /////////////////////////////////////////////////////// + static DestFinfo process( "process", + "Handles process call", + new ProcOpFunc< RandSpike >( &RandSpike::process ) ); + static DestFinfo reinit( "reinit", + "Handles reinit call", + new ProcOpFunc< RandSpike >( &RandSpike::reinit ) ); + + static Finfo* processShared[] = + { + &process, &reinit + }; + + static SharedFinfo proc( "proc", + "Shared message to receive Process message from scheduler", + processShared, sizeof( processShared ) / sizeof( Finfo* ) ); + + ////////////////////////////////////////////////////////////////// + // Dest Finfos. + ////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////// + // Value Finfos. + ////////////////////////////////////////////////////////////////// + + static ValueFinfo< RandSpike, double > rate( "rate", + "Specifies rate for random spike train. Note that this is" + "probabilistic, so the instantaneous rate may differ. " + "If the rate is assigned be message and it varies slowly then " + "the average firing rate will approach the specified rate", + &RandSpike::setRate, + &RandSpike::getRate + ); + static ValueFinfo< RandSpike, double > refractT( "refractT", + "Refractory Time.", + &RandSpike::setRefractT, + &RandSpike::getRefractT + ); + static ValueFinfo< RandSpike, double > absRefract( "abs_refract", + "Absolute refractory time. Synonym for refractT.", + &RandSpike::setRefractT, + &RandSpike::getRefractT + ); + static ValueFinfo< RandSpike, bool > doPeriodic( "doPeriodic", + "Flag: when false, do Poisson process with specified mean rate.\n" + "When true, fire periodically at specified rate.\n" + "Defaults to false. Note that refractory time overrides this: " + "Rate cannot exceed 1/refractT.", + &RandSpike::setDoPeriodic, + &RandSpike::getDoPeriodic + ); + static ReadOnlyValueFinfo< RandSpike, bool > hasFired( "hasFired", + "True if RandSpike has just fired", + &RandSpike::getFired + ); + + static Finfo* spikeGenFinfos[] = + { + spikeOut(), // SrcFinfo + &proc, // Shared + &rate, // Value + &refractT, // Value + &absRefract, // Value + &doPeriodic, // Value + &hasFired, // ReadOnlyValue + }; + + static string doc[] = + { + "Name", "RandSpike", + "Author", "Upi Bhalla", + "Description", "RandSpike object, generates random or regular " + "spikes at " + "specified mean rate. Based closely on GENESIS randspike. " + }; + static Dinfo< RandSpike > dinfo; + static Cinfo spikeGenCinfo( + "RandSpike", + Neutral::initCinfo(), + spikeGenFinfos, sizeof( spikeGenFinfos ) / sizeof( Finfo* ), + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); + + return &spikeGenCinfo; } static const Cinfo* spikeGenCinfo = RandSpike::initCinfo(); RandSpike::RandSpike() - : - rate_( 0.0 ), - realRate_( 0.0 ), - refractT_(0.0), - lastEvent_(0.0), - threshold_(0.0), - fired_( false ), - doPeriodic_( false ) -{;} + : + rate_( 0.0 ), + realRate_( 0.0 ), + refractT_(0.0), + lastEvent_(0.0), + threshold_(0.0), + fired_( false ), + doPeriodic_( false ) +{ + ; +} ////////////////////////////////////////////////////////////////// // Here we put the RandSpike class functions. @@ -132,45 +136,49 @@ RandSpike::RandSpike() // Value Field access function definitions. void RandSpike::setRate( double rate ) { - if ( rate < 0.0 ) { - cout <<"Warning: RandSpike::setRate: Rate must be >= 0. Using 0.\n"; - rate = 0.0; - } - rate_ = rate; - double prob = 1.0 - rate * refractT_; - if ( prob <= 0.0 ) { - cout << "Warning: RandSpike::setRate: Rate is too high compared to refractory time\n"; - realRate_ = rate_; - } else { - realRate_ = rate_ / prob; - } + if ( rate < 0.0 ) + { + cout <<"Warning: RandSpike::setRate: Rate must be >= 0. Using 0.\n"; + rate = 0.0; + } + rate_ = rate; + double prob = 1.0 - rate * refractT_; + if ( prob <= 0.0 ) + { + cout << "Warning: RandSpike::setRate: Rate is too high compared to refractory time\n"; + realRate_ = rate_; + } + else + { + realRate_ = rate_ / prob; + } } double RandSpike::getRate() const { - return rate_; + return rate_; } void RandSpike::setRefractT( double val ) { - refractT_ = val; + refractT_ = val; } double RandSpike::getRefractT() const { - return refractT_; + return refractT_; } bool RandSpike::getFired() const { - return fired_; + return fired_; } void RandSpike::setDoPeriodic( bool val ) { - doPeriodic_ = val; + doPeriodic_ = val; } bool RandSpike::getDoPeriodic() const { - return doPeriodic_; + return doPeriodic_; } @@ -180,35 +188,43 @@ bool RandSpike::getDoPeriodic() const void RandSpike::process( const Eref& e, ProcPtr p ) { - if ( refractT_ > p->currTime - lastEvent_ || rate_ <= 0.0 ) - return; - fired_ = false; - if (doPeriodic_) { - if ( (p->currTime - lastEvent_) > 1.0/rate_ ) { - lastEvent_ = p->currTime; - spikeOut()->send( e, p->currTime ); - fired_ = true; - } - } else { - double prob = realRate_ * p->dt; - if ( prob >= 1.0 || prob >= mtrand() ) - { - lastEvent_ = p->currTime; - spikeOut()->send( e, p->currTime ); - fired_ = true; - } - } + if ( refractT_ > p->currTime - lastEvent_ || rate_ <= 0.0 ) + return; + + fired_ = false; + if (doPeriodic_) + { + if ( (p->currTime - lastEvent_) > 1.0/rate_ ) + { + lastEvent_ = p->currTime; + spikeOut()->send( e, p->currTime ); + fired_ = true; + } + } + else + { + double prob = realRate_ * p->dt; + if ( prob >= 1.0 || prob >= moose::mtrand() ) + { + lastEvent_ = p->currTime; + spikeOut()->send( e, p->currTime ); + fired_ = true; + } + } } // Set it so that first spike is allowed. void RandSpike::reinit( const Eref& e, ProcPtr p ) { - if ( rate_ <= 0.0 ) { - lastEvent_ = 0.0; - realRate_ = 0.0; - } else { - double prob = mtrand(); - double m = 1.0 / rate_; - lastEvent_ = m * log( prob ); - } + if ( rate_ <= 0.0 ) + { + lastEvent_ = 0.0; + realRate_ = 0.0; + } + else + { + double prob = moose::mtrand(); + double m = 1.0 / rate_; + lastEvent_ = m * log( prob ); + } } diff --git a/moose-core/biophysics/RandSpike.h b/moose-core/biophysics/RandSpike.h index 2a7da3de72c1ead13a743483faf5bbc0496c331a..682c1911bf39987301549cc86d8b0370c0e43495 100644 --- a/moose-core/biophysics/RandSpike.h +++ b/moose-core/biophysics/RandSpike.h @@ -12,40 +12,41 @@ class RandSpike { - public: +public: RandSpike(); - ////////////////////////////////////////////////////////////////// - // Field functions. - ////////////////////////////////////////////////////////////////// - void setRate( double rate ); - double getRate() const; - - void setRefractT( double val ); - double getRefractT() const; - - void setDoPeriodic( bool val ); - bool getDoPeriodic() const; - - bool getFired() const; - - ////////////////////////////////////////////////////////////////// - // Message dest functions. - ////////////////////////////////////////////////////////////////// - - void process( const Eref& e, ProcPtr p ); - void reinit( const Eref& e, ProcPtr p ); - - ////////////////////////////////////////////////////////////////// - static const Cinfo* initCinfo(); - private: - double rate_; - double realRate_; - double refractT_; - double lastEvent_; - double threshold_; - bool fired_; - bool doPeriodic_; + ////////////////////////////////////////////////////////////////// + // Field functions. + ////////////////////////////////////////////////////////////////// + void setRate( double rate ); + double getRate() const; + + void setRefractT( double val ); + double getRefractT() const; + + void setDoPeriodic( bool val ); + bool getDoPeriodic() const; + + bool getFired() const; + + ////////////////////////////////////////////////////////////////// + // Message dest functions. + ////////////////////////////////////////////////////////////////// + + void process( const Eref& e, ProcPtr p ); + void reinit( const Eref& e, ProcPtr p ); + + ////////////////////////////////////////////////////////////////// + static const Cinfo* initCinfo(); +private: + double rate_; + double realRate_; + double refractT_; + double lastEvent_; + double threshold_; + bool fired_; + bool doPeriodic_; + }; #endif // _RANDSPIKE_H diff --git a/moose-core/biophysics/testBiophysics.cpp b/moose-core/biophysics/testBiophysics.cpp index c3069e332af55eec3310582abcdae2dd784c7bc5..e46b301257df547e76df987351834ad522b33d06 100644 --- a/moose-core/biophysics/testBiophysics.cpp +++ b/moose-core/biophysics/testBiophysics.cpp @@ -8,30 +8,19 @@ **********************************************************************/ -#include "header.h" +#include "../basecode/header.h" +#include "../basecode/global.h" #include "../shell/Shell.h" -#include "../randnum/randnum.h" -#include "CompartmentBase.h" #include "../utility/testing_macros.hpp" +#include "CompartmentBase.h" #include "Compartment.h" -/* -#include "HHGate.h" -#include "ChanBase.h" -#include "HHChannel.h" -*/ + extern void testCompartment(); // Defined in Compartment.cpp extern void testCompartmentProcess(); // Defined in Compartment.cpp extern void testMarkovRateTable(); //Defined in MarkovRateTable.cpp extern void testVectorTable(); //Defined in VectorTable.cpp -/* -extern void testSpikeGen(); // Defined in SpikeGen.cpp -extern void testCaConc(); // Defined in CaConc.cpp -extern void testNernst(); // Defined in Nernst.cpp -extern void testMarkovSolverBase(); //Defined in MarkovSolverBase.cpp -extern void testMarkovSolver(); //Defined in MarkovSolver.cpp -*/ #ifdef DO_UNIT_TESTS @@ -46,7 +35,7 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) static const double delayMax = 4; static const double delayMin = 0; static const double connectionProbability = 0.1; - static const unsigned int NUM_TOT_SYN = 104576; + static const unsigned int NUM_TOT_SYN = 104831; unsigned int size = 1024; string arg; Eref sheller( Id().eref() ); @@ -77,7 +66,9 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) unsigned int nd = syn->totNumLocalField(); if ( Shell::numNodes() == 1 ) - assert( nd == NUM_TOT_SYN ); + { + EXPECT_EQ( nd, NUM_TOT_SYN, "" ); + } else if ( Shell::numNodes() == 2 ) assert( nd == 52446 ); else if ( Shell::numNodes() == 3 ) @@ -114,8 +105,11 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) // by multiple threads if the above Set call is not complete. vector< double > origVm( size, 0.0 ); + + // NOTE: From + moose::mtseed( 5489UL ); for ( unsigned int i = 0; i < size; ++i ) - origVm[i] = mtrand() * Vmax; + origVm[i] = moose::mtrand() * Vmax; double origVm100 = origVm[100]; double origVm900 = origVm[900]; @@ -146,11 +140,10 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) vector< double > delay( numSynVec[i], 0.0 ); for ( unsigned int j = 0; j < numSynVec[i]; ++j ) { - weight[i][ j ] = mtrand() * weightMax; - delay[ j ] = delayMin + mtrand() * ( delayMax - delayMin ); + weight[i][ j ] = moose::mtrand() * weightMax; + delay[ j ] = delayMin + moose::mtrand() * ( delayMax - delayMin ); } - ret = Field< double >:: - setVec( ObjId( synId, i ), "weight", weight[i] ); + ret = Field< double >::setVec( ObjId( synId, i ), "weight", weight[i] ); assert( ret ); ret = Field< double >::setVec( ObjId( synId, i ), "delay", delay ); assert( ret ); @@ -218,13 +211,24 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) ASSERT_DOUBLE_EQ("", retVm901, 0.28303358631241327 ); ASSERT_DOUBLE_EQ("", retVm902, 0.0096374021108587178 ); */ - ASSERT_DOUBLE_EQ("", retVm100, 0.069517018453329804 ); - ASSERT_DOUBLE_EQ("", retVm101, 0.32823493598699577 ); - ASSERT_DOUBLE_EQ("", retVm102, 0.35036493874475361 ); - ASSERT_DOUBLE_EQ("", retVm99, 0.04087358817787364 ); - ASSERT_DOUBLE_EQ("", retVm900, 0.26414663635984065 ); - ASSERT_DOUBLE_EQ("", retVm901, 0.39864519810259352 ); - ASSERT_DOUBLE_EQ("", retVm902, 0.04818717439429359 ); + +#if 0 + cout << endl; + cout << std::setprecision(12) << retVm100 << endl; + cout << std::setprecision(12) << retVm101 << endl; + cout << std::setprecision(12) << retVm102 << endl; + cout << std::setprecision(11) << retVm99 << endl; + cout << std::setprecision(12) << retVm900 << endl; + cout << std::setprecision(12) << retVm901 << endl; + cout << std::setprecision(12) << retVm902 << endl; +#endif + ASSERT_DOUBLE_EQ("", retVm100, 0.0752853031478); + ASSERT_DOUBLE_EQ("", retVm101, 0.226731547886 ); + ASSERT_DOUBLE_EQ("", retVm102, 0.204294350789 ); + ASSERT_DOUBLE_EQ("", retVm99, 0.2814616871 ); + ASSERT_DOUBLE_EQ("", retVm900, 0.194820080944 ); + ASSERT_DOUBLE_EQ("", retVm901, 0.0490452677121); + ASSERT_DOUBLE_EQ("", retVm902, 0.214295483534 ); } /* diff --git a/moose-core/builtins/Table.h b/moose-core/builtins/Table.h index 9fb78c8b69f5416c999d3383708c58f127e50be8..34397cde40e0056b5a57517d54831db73cbc9b52 100644 --- a/moose-core/builtins/Table.h +++ b/moose-core/builtins/Table.h @@ -10,10 +10,6 @@ #ifndef _TABLE_H #define _TABLE_H - -#if USE_BOOST -#include <boost/filesystem.hpp> -#endif /* ----- USE_BOOST ----- */ #include <fstream> /** diff --git a/moose-core/builtins/testNSDF.cpp b/moose-core/builtins/testNSDF.cpp index b99782f1e4c7280cfcc17dbf11bd1cf39469e395..86e1f96f04746ceef3930f771dfec5603679884f 100644 --- a/moose-core/builtins/testNSDF.cpp +++ b/moose-core/builtins/testNSDF.cpp @@ -73,7 +73,7 @@ void testCreateStringDataset() hsize_t size = STR_DSET_LEN; herr_t status; HDF5WriterBase writer; - string h5Filename = std::tmpnam( NULL ); + string h5Filename = moose::random_string( 10 ); file = H5Fcreate(h5Filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); dset = writer.createStringDataset(file, STR_DSET_NAME, size, size); assert(dset >= 0); diff --git a/moose-core/diffusion/ConcChanInfo.h b/moose-core/diffusion/ConcChanInfo.h index cd16266b5e5ea895ce7a2fec5722bb18de339a50..caf2b6b4d460b897dfd28134069f59f4163d3acf 100644 --- a/moose-core/diffusion/ConcChanInfo.h +++ b/moose-core/diffusion/ConcChanInfo.h @@ -17,14 +17,18 @@ class ConcChanInfo public: ConcChanInfo(); ConcChanInfo( unsigned int my, unsigned int other, - unsigned int chan, double perm ) + unsigned int chan, double perm, bool isSwapped ) : myPool( my ), otherPool( other ), chanPool( chan ), + swapped( isSwapped ), permeability( perm ) {;} unsigned int myPool; unsigned int otherPool; unsigned int chanPool; + bool swapped; // Flag records whether myPool/otherPool are + // swapped wrt inPool/outPool. System expects + // that inPool should be in same compt as chanPool. double permeability; }; diff --git a/moose-core/diffusion/DiffPoolVec.cpp b/moose-core/diffusion/DiffPoolVec.cpp index cd1da649567100c4a3de2008d96c0d2d0ebd24ff..d8a9208dcc779ae82ff63783bc86a40be4c17f05 100644 --- a/moose-core/diffusion/DiffPoolVec.cpp +++ b/moose-core/diffusion/DiffPoolVec.cpp @@ -23,135 +23,140 @@ using namespace std; * work on in single-compartment models. */ DiffPoolVec::DiffPoolVec() - : id_( 0 ), n_( 1, 0.0 ), nInit_( 1, 0.0 ), - diffConst_( 1.0e-12 ), motorConst_( 0.0 ) -{;} + : id_( 0 ), n_( 1, 0.0 ), nInit_( 1, 0.0 ), + diffConst_( 1.0e-12 ), motorConst_( 0.0 ) +{ + ; +} double DiffPoolVec::getNinit( unsigned int voxel ) const { - assert( voxel < nInit_.size() ); - return nInit_[ voxel ]; + assert( voxel < nInit_.size() ); + return nInit_[ voxel ]; } void DiffPoolVec::setNinit( unsigned int voxel, double v ) { - assert( voxel < nInit_.size() ); - nInit_[ voxel ] = v; + assert( voxel < nInit_.size() ); + nInit_[ voxel ] = v; } double DiffPoolVec::getN( unsigned int voxel ) const { - assert( voxel < n_.size() ); - return n_[ voxel ]; + assert( voxel < n_.size() ); + return n_[ voxel ]; } void DiffPoolVec::setN( unsigned int voxel, double v ) { - assert( voxel < n_.size() ); - n_[ voxel ] = v; + assert( voxel < n_.size() ); + n_[ voxel ] = v; } double DiffPoolVec::getPrev( unsigned int voxel ) const { - assert( voxel < n_.size() ); - return prev_[ voxel ]; + assert( voxel < n_.size() ); + return prev_[ voxel ]; } const vector< double >& DiffPoolVec::getNvec() const { - return n_; + return n_; } void DiffPoolVec::setNvec( const vector< double >& vec ) { - assert( vec.size() == n_.size() ); - n_ = vec; + assert( vec.size() == n_.size() ); + n_ = vec; } void DiffPoolVec::setNvec( unsigned int start, unsigned int num, - vector< double >::const_iterator q ) + vector< double >::const_iterator q ) { - assert( start + num <= n_.size() ); - vector< double >::iterator p = n_.begin() + start; - for ( unsigned int i = 0; i < num; ++i ) - *p++ = *q++; + assert( start + num <= n_.size() ); + vector< double >::iterator p = n_.begin() + start; + for ( unsigned int i = 0; i < num; ++i ) + *p++ = *q++; } void DiffPoolVec::setPrevVec() { - prev_ = n_; + prev_ = n_; } double DiffPoolVec::getDiffConst() const { - return diffConst_; + return diffConst_; } void DiffPoolVec::setDiffConst( double v ) { - diffConst_ = v; + diffConst_ = v; } double DiffPoolVec::getMotorConst() const { - return motorConst_; + return motorConst_; } void DiffPoolVec::setMotorConst( double v ) { - motorConst_ = v; + motorConst_ = v; } void DiffPoolVec::setNumVoxels( unsigned int num ) { - nInit_.resize( num, 0.0 ); - n_.resize( num, 0.0 ); + nInit_.resize( num, 0.0 ); + n_.resize( num, 0.0 ); } unsigned int DiffPoolVec::getNumVoxels() const { - return n_.size(); + return n_.size(); } void DiffPoolVec::setId( unsigned int id ) { - id_ = id; + id_ = id; } unsigned int DiffPoolVec::getId() const { - return id_; + return id_; } void DiffPoolVec::setOps(const vector< Triplet< double > >& ops, - const vector< double >& diagVal ) + const vector< double >& diagVal ) { - if ( ops.size() > 0 ) { - assert( diagVal.size() == n_.size() ); - ops_ = ops; - diagVal_ = diagVal; - } else { - ops_.clear(); - diagVal_.clear(); - } + if ( ops.size() > 0 ) + { + assert( diagVal.size() == n_.size() ); + ops_ = ops; + diagVal_ = diagVal; + } + else + { + ops_.clear(); + diagVal_.clear(); + } } void DiffPoolVec::advance( double dt ) { - if ( ops_.size() == 0 ) return; - for ( vector< Triplet< double > >::const_iterator - i = ops_.begin(); i != ops_.end(); ++i ) - n_[i->c_] -= n_[i->b_] * i->a_; + if ( ops_.size() == 0 ) return; + for ( vector< Triplet< double > >::const_iterator + i = ops_.begin(); i != ops_.end(); ++i ) + n_[i->c_] -= n_[i->b_] * i->a_; - assert( n_.size() == diagVal_.size() ); - vector< double >::iterator iy = n_.begin(); - for ( vector< double >::const_iterator - i = diagVal_.begin(); i != diagVal_.end(); ++i ) - *iy++ *= *i; + assert( n_.size() == diagVal_.size() ); + vector< double >::iterator iy = n_.begin(); + for ( vector< double >::const_iterator + i = diagVal_.begin(); i != diagVal_.end(); ++i ) + *iy++ *= *i; } void DiffPoolVec::reinit() // Not called by the clock, but by parent. { - assert( n_.size() == nInit_.size() ); - prev_ = n_ = nInit_; + assert( n_.size() == nInit_.size() ); + prev_ = n_ = nInit_; } diff --git a/moose-core/diffusion/Dsolve.cpp b/moose-core/diffusion/Dsolve.cpp index d2f27122fe4eb2a9777200d76468671fa4e99cb8..ec72a97e737e06f9dc64a21f949c2047f5a49a3f 100644 --- a/moose-core/diffusion/Dsolve.cpp +++ b/moose-core/diffusion/Dsolve.cpp @@ -374,33 +374,30 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt ) { // Each jn has some channels // Each channel has a chanPool, an intPool and an extPool. - // intPool is on self, extPool is on other, but we have a problem + // chanPool and intPool must be on self, extPool is on other. In + // cases where the intPool is on other, it attempts to swap the + // int and ext pools, but this too could fail // because the chanPool could be a third compartment, such as the memb - // If we stipulate it is is on self, that is easy but not general. + // + // Don't have a solution for this case as yet. // Other alternative is to have a message to update the N of the chan, // so it isn't in the domain of the solver at all except for here. // In which case we will want to point to the Moose object for it. // - // for ( unsigned int i = 0; i < jn.myChannels.size(); ++i ) { ConcChanInfo& myChan = channels_[ jn.myChannels[i] ]; DiffPoolVec& myDv = pools_[ myChan.myPool ]; DiffPoolVec& otherDv = other->pools_[ myChan.otherPool ]; DiffPoolVec& chanDv = pools_[ myChan.chanPool ]; - /* - DiffPoolVec& myDv = pools_[ jn.myPools[myChan.myPool] ]; - DiffPoolVec& otherDv = - other->pools_[ jn.otherPools[myChan.otherPool] ]; - DiffPoolVec& chanDv = pools_[ jn.myPools[myChan.chanPool] ]; - */ for ( vector< VoxelJunction >::const_iterator j = jn.vj.begin(); j != jn.vj.end(); ++j ) { double myN = myDv.getN( j->first ); double lastN = myN; double otherN = otherDv.getN( j->second ); - double perm = myChan.permeability * chanDv.getN( j->first ); + double chanN = chanDv.getN( j->first ); + double perm = myChan.permeability * chanN / NA; myN = integ( myN, perm * myN/j->firstVol, perm * otherN/j->secondVol, dt ); otherN += lastN - myN; // Mass consv @@ -433,7 +430,8 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt ) double myN = myDv.getN( j->first ); double lastN = myN; double otherN = otherDv.getN( j->second ); - double perm = otherChan.permeability * chanDv.getN(j->second); + double chanN = chanDv.getN( j->second ); + double perm = otherChan.permeability * chanN / NA; myN = integ( myN, perm * myN/j->firstVol, perm * otherN/j->secondVol, dt ); otherN += lastN - myN; // Mass consv @@ -571,18 +569,22 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans ) if (i->element()->getNeighbors( ret, chanPoolFinfo ) == 0 ) return; ObjId chanPool( ret[0] ); ret.clear(); - /* - ObjId inPool = i->element()->findCaller( fin ); - ObjId chanPool = i->element()->findCaller( fchan ); - ObjId outPool = i->element()->findCaller( fout ); - */ + unsigned int outPoolValue = outPool.id.value(); + bool swapped = false; if ( !( inPool.bad() or chanPool.bad() ) ) { unsigned int inPoolIndex = convertIdToPoolIndex( inPool.id ); unsigned int chanPoolIndex = convertIdToPoolIndex(chanPool.id); - if ( inPoolIndex != ~0U && chanPoolIndex != ~0U ) { - ConcChanInfo cci( inPoolIndex, outPool.id.value(), - chanPoolIndex, - Field< double >::get( *i, "permeability" ) + if ( inPoolIndex == ~0U ) { // Swap in and out as chan is symm + inPoolIndex = convertIdToPoolIndex( outPool.id ); + outPoolValue = inPool.id.value(); + swapped = true; + } + if ( ( inPoolIndex != ~0U) && (chanPoolIndex != ~0U ) ) { + ConcChanInfo cci( + inPoolIndex, outPoolValue, chanPoolIndex, + Field< double >::get( *i, "permeability" ), + ////// Fix it below //////// + swapped ); channels_.push_back( cci ); } @@ -895,19 +897,23 @@ void Dsolve::mapChansBetweenDsolves( DiffJunction& jn, Id self, Id other) vector< ConcChanInfo >& ch = selfSolve->channels_; unsigned int outIndex; for ( unsigned int i = 0; i < ch.size(); ++i ) { + unsigned int chanIndex = ch[i].chanPool; outIndex = otherSolve->convertIdToPoolIndex( ch[i].otherPool ); - if ( outIndex != ~0U ) { + if ( (outIndex != ~0U) && (chanIndex != ~0U ) ) { jn.myChannels.push_back(i); ch[i].otherPool = outIndex; // replace the Id with the index. + ch[i].chanPool = chanIndex; //chanIndex may be on either Dsolve } } // Now set up the other Dsolve. vector< ConcChanInfo >& ch2 = otherSolve->channels_; for ( unsigned int i = 0; i < ch2.size(); ++i ) { + unsigned int chanIndex = ch2[i].chanPool; outIndex = selfSolve->convertIdToPoolIndex( ch2[i].otherPool ); - if ( outIndex != ~0U ) { + if ( (outIndex != ~0U) && (chanIndex != ~0U) ) { jn.otherChannels.push_back(i); ch2[i].otherPool = outIndex; // replace the Id with the index + ch2[i].chanPool = chanIndex; //chanIndex may be on either Dsolve } } } diff --git a/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp b/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp index 2c2531c93010a797ebc71497106b5ef253f1c6ac..472ef3675b2f9e2b23f409c6e3b25e860a99722d 100644 --- a/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp +++ b/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp @@ -140,7 +140,9 @@ namespace boost { namespace numeric { namespace bindings { >::value)); #endif +#ifndef NDEBUG typedef typename MatrA::value_type value_type ; +#endif int const n = traits::matrix_size1 (a); assert (n == traits::matrix_size2 (a)); @@ -185,7 +187,9 @@ namespace boost { namespace numeric { namespace bindings { >::value)); #endif +#ifndef NDEBUG typedef typename MatrA::value_type value_type ; +#endif int const n = traits::matrix_size1 (a); assert (n == traits::matrix_size2 (a)); @@ -265,7 +269,9 @@ namespace boost { namespace numeric { namespace bindings { inline int operator() (char jobvs, MatrA& a, EigVal& w, SchVec& vs, optimal_workspace ) const { typedef typename MatrA::value_type value_type ; +#ifndef NDEBUG typedef typename traits::type_traits< value_type >::real_type real_type ; +#endif int n = traits::matrix_size1( a ); @@ -278,7 +284,10 @@ namespace boost { namespace numeric { namespace bindings { inline int operator() (char jobvs, MatrA& a, EigVal& w, SchVec& vs, minimal_workspace ) const { typedef typename MatrA::value_type value_type ; + +#ifndef NDEBUG typedef typename traits::type_traits< value_type >::real_type real_type ; +#endif int n = traits::matrix_size1( a ); diff --git a/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp b/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp index 0bb01fdbc8a35d2727d8f32434d04ff3e84fef86..eba01080e51873fcf9d4658db99bec7d58186620 100644 --- a/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp +++ b/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp @@ -295,7 +295,9 @@ namespace boost { namespace numeric { namespace bindings { || (jobvt == 'A' && traits::leading_dimension (vt) >= n) || (jobvt == 'S' && traits::leading_dimension (vt) >= minmn)); #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS +#ifndef NDEBUG typedef typename traits::matrix_traits<MatrA>::value_type val_t; +#endif #else typedef typename MatrA::value_type val_t; #endif diff --git a/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp b/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp index 5aeaf382adf18cf3f9925cb9f8491d666cc1f5d1..fdd5253bcb68669e51e9d871090d254280cb1fc0 100644 --- a/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp +++ b/moose-core/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp @@ -136,7 +136,10 @@ namespace boost { namespace numeric { namespace bindings { template <typename A, typename W, typename Work> inline int syev (char jobz, char uplo, A& a, W& w, detail::workspace1<Work> workspace ) { + +#ifndef NDEBUG typedef typename A::value_type value_type ; +#endif return detail::syev(jobz, uplo, a, w, workspace.w_); } // syev() @@ -195,7 +198,9 @@ namespace boost { namespace numeric { namespace bindings { template <typename A, typename W, typename Work> inline int syev (char jobz, A& a, W& w, detail::workspace1<Work> workspace ) { +#ifndef NDEBUG typedef typename A::value_type value_type ; +#endif char uplo = traits::matrix_uplo_tag( a ) ; #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK typedef typename traits::matrix_traits<A>::matrix_structure matrix_structure ; diff --git a/moose-core/intfire/CMakeLists.txt b/moose-core/intfire/CMakeLists.txt index 5ee3c2fbad84ca9f879136eabec4b0410bf60589..06435a8e055245679563e08a99a360d05b3cddd6 100644 --- a/moose-core/intfire/CMakeLists.txt +++ b/moose-core/intfire/CMakeLists.txt @@ -1,14 +1,5 @@ -cmake_minimum_required(VERSION 2.6) -INCLUDE_DIRECTORIES(../basecode) - -ADD_LIBRARY(intfire - AdExIF.cpp - AdThreshIF.cpp - ExIF.cpp - IntFireBase.cpp - IzhIF.cpp - LIF.cpp - QIF.cpp - testIntFire.cpp - ) - +cmake_minimum_required(VERSION 2.8) +include_directories(../basecode) +add_definitions( -std=c++11 ) +file(GLOB SRC *.cpp) +add_library(intfire ${SRC}) diff --git a/moose-core/intfire/IntFireBase.cpp b/moose-core/intfire/IntFireBase.cpp index a4364db48894e3dbb98105963f8311cb692d025e..7488c54ffca9948c52ae4fe702720bf8d9c64d5f 100644 --- a/moose-core/intfire/IntFireBase.cpp +++ b/moose-core/intfire/IntFireBase.cpp @@ -7,97 +7,99 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" -#include "ElementValueFinfo.h" +#include "../basecode/header.h" +#include "../basecode/ElementValueFinfo.h" #include "../biophysics/CompartmentBase.h" #include "../biophysics/Compartment.h" #include "IntFireBase.h" using namespace moose; -SrcFinfo1< double >* IntFireBase::spikeOut() { - static SrcFinfo1< double > spikeOut( - "spikeOut", - "Sends out spike events. The argument is the timestamp of " - "the spike. " - ); - return &spikeOut; +SrcFinfo1< double >* IntFireBase::spikeOut() +{ + static SrcFinfo1< double > spikeOut( + "spikeOut", + "Sends out spike events. The argument is the timestamp of " + "the spike. " + ); + return &spikeOut; } const Cinfo* IntFireBase::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions - ////////////////////////////////////////////////////////////// - - static ElementValueFinfo< IntFireBase, double > thresh( - "thresh", - "firing threshold", - &IntFireBase::setThresh, - &IntFireBase::getThresh - ); - - static ElementValueFinfo< IntFireBase, double > vReset( - "vReset", - "voltage is set to vReset after firing", - &IntFireBase::setVReset, - &IntFireBase::getVReset - ); - - static ElementValueFinfo< IntFireBase, double > refractoryPeriod( - "refractoryPeriod", - "Minimum time between successive spikes", - &IntFireBase::setRefractoryPeriod, - &IntFireBase::getRefractoryPeriod - ); - - static ReadOnlyElementValueFinfo< IntFireBase, double > lastEventTime( - "lastEventTime", - "Timestamp of last firing.", - &IntFireBase::getLastEventTime - ); - - static ReadOnlyElementValueFinfo< IntFireBase, bool > hasFired( - "hasFired", - "The object has fired within the last timestep", - &IntFireBase::hasFired - ); - ////////////////////////////////////////////////////////////// - // MsgDest Definitions - ////////////////////////////////////////////////////////////// - static DestFinfo activation( "activation", - "Handles value of synaptic activation arriving on this object", - new OpFunc1< IntFireBase, double >( &IntFireBase::activation )); - - ////////////////////////////////////////////////////////////// - - static Finfo* intFireFinfos[] = { - &thresh, // Value - &vReset, // Value - &refractoryPeriod, // Value - &hasFired, // ReadOnlyValue - &lastEventTime, // ReadOnlyValue - &activation, // DestFinfo - IntFireBase::spikeOut() // MsgSrc - }; - - static string doc[] = - { - "Name", "IntFireBase", - "Author", "Upi Bhalla", - "Description", "Base class for Integrate-and-fire compartment.", - }; + ////////////////////////////////////////////////////////////// + // Field Definitions + ////////////////////////////////////////////////////////////// + static ElementValueFinfo< IntFireBase, double > thresh( + "thresh", + "firing threshold", + &IntFireBase::setThresh, + &IntFireBase::getThresh + ); + + static ElementValueFinfo< IntFireBase, double > vReset( + "vReset", + "voltage is set to vReset after firing", + &IntFireBase::setVReset, + &IntFireBase::getVReset + ); + + static ElementValueFinfo< IntFireBase, double > refractoryPeriod( + "refractoryPeriod", + "Minimum time between successive spikes", + &IntFireBase::setRefractoryPeriod, + &IntFireBase::getRefractoryPeriod + ); + + static ReadOnlyElementValueFinfo< IntFireBase, double > lastEventTime( + "lastEventTime", + "Timestamp of last firing.", + &IntFireBase::getLastEventTime + ); + + static ReadOnlyElementValueFinfo< IntFireBase, bool > hasFired( + "hasFired", + "The object has fired within the last timestep", + &IntFireBase::hasFired + ); + ////////////////////////////////////////////////////////////// + // MsgDest Definitions + ////////////////////////////////////////////////////////////// + static DestFinfo activation( + "activation", + "Handles value of synaptic activation arriving on this object", + new OpFunc1< IntFireBase, double >( &IntFireBase::activation )); + + ////////////////////////////////////////////////////////////// + + static Finfo* intFireFinfos[] = + { + &thresh, // Value + &vReset, // Value + &refractoryPeriod, // Value + &hasFired, // ReadOnlyValue + &lastEventTime, // ReadOnlyValue + &activation, // DestFinfo + IntFireBase::spikeOut() // MsgSrc + }; + + static string doc[] = + { + "Name", "IntFireBase", + "Author", "Upi Bhalla", + "Description", "Base class for Integrate-and-fire compartment.", + }; static ZeroSizeDinfo< int > dinfo; - static Cinfo intFireBaseCinfo( - "IntFireBase", - Compartment::initCinfo(), - intFireFinfos, - sizeof( intFireFinfos ) / sizeof (Finfo*), - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); - - return &intFireBaseCinfo; + static Cinfo intFireBaseCinfo( + "IntFireBase", + Compartment::initCinfo(), + intFireFinfos, + sizeof( intFireFinfos ) / sizeof (Finfo*), + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); + + return &intFireBaseCinfo; } static const Cinfo* intFireBaseCinfo = IntFireBase::initCinfo(); @@ -107,59 +109,59 @@ static const Cinfo* intFireBaseCinfo = IntFireBase::initCinfo(); ////////////////////////////////////////////////////////////////// IntFireBase::IntFireBase() - : - threshold_( 0.0 ), - vReset_( 0.0 ), - activation_( 0.0 ), - refractT_( 0.0 ), - lastEvent_( 0.0 ), - fired_( false ) + : + threshold_( 0.0 ), + vReset_( 0.0 ), + activation_( 0.0 ), + refractT_( 0.0 ), + lastEvent_( 0.0 ), + fired_( false ) {;} IntFireBase::~IntFireBase() { - ; + ; } // Value Field access function definitions. void IntFireBase::setThresh( const Eref& e, double val ) { - threshold_ = val; + threshold_ = val; } double IntFireBase::getThresh( const Eref& e ) const { - return threshold_; + return threshold_; } void IntFireBase::setVReset( const Eref& e, double val ) { - vReset_ = val; + vReset_ = val; } double IntFireBase::getVReset( const Eref& e ) const { - return vReset_; + return vReset_; } void IntFireBase::setRefractoryPeriod( const Eref& e, double val ) { - refractT_ = val; + refractT_ = val; } double IntFireBase::getRefractoryPeriod( const Eref& e ) const { - return refractT_; + return refractT_; } double IntFireBase::getLastEventTime( const Eref& e ) const { - return lastEvent_; + return lastEvent_; } bool IntFireBase::hasFired( const Eref& e ) const { - return fired_; + return fired_; } ////////////////////////////////////////////////////////////////// @@ -168,5 +170,5 @@ bool IntFireBase::hasFired( const Eref& e ) const void IntFireBase::activation( double v ) { - activation_ += v; + activation_ += v; } diff --git a/moose-core/intfire/IntFireBase.h b/moose-core/intfire/IntFireBase.h index c17dbdcabf6f62ae9ccf66565b45b1daa9660aa0..bbdc12d54f6578130bc39d67450701ee910d93dd 100644 --- a/moose-core/intfire/IntFireBase.h +++ b/moose-core/intfire/IntFireBase.h @@ -18,52 +18,52 @@ namespace moose */ class IntFireBase: public Compartment { - public: - IntFireBase(); - virtual ~IntFireBase(); +public: + IntFireBase(); + virtual ~IntFireBase(); - // Value Field access function definitions. - void setThresh( const Eref& e, double val ); - double getThresh( const Eref& e ) const; - void setVReset( const Eref& e, double val ); - double getVReset( const Eref& e ) const; - void setRefractoryPeriod( const Eref& e, double val ); - double getRefractoryPeriod( const Eref& e ) const; - double getLastEventTime( const Eref& e ) const; - bool hasFired( const Eref& e ) const; + // Value Field access function definitions. + void setThresh( const Eref& e, double val ); + double getThresh( const Eref& e ) const; + void setVReset( const Eref& e, double val ); + double getVReset( const Eref& e ) const; + void setRefractoryPeriod( const Eref& e, double val ); + double getRefractoryPeriod( const Eref& e ) const; + double getLastEventTime( const Eref& e ) const; + bool hasFired( const Eref& e ) const; - // Dest function definitions. - /** - * The process function does the object updating and sends out - * messages to channels, nernsts, and so on. - */ - virtual void vProcess( const Eref& e, ProcPtr p ) = 0; + // Dest function definitions. + /** + * The process function does the object updating and sends out + * messages to channels, nernsts, and so on. + */ + virtual void vProcess( const Eref& e, ProcPtr p ) = 0; - /** - * The reinit function reinitializes all fields. - */ - virtual void vReinit( const Eref& e, ProcPtr p ) = 0; + /** + * The reinit function reinitializes all fields. + */ + virtual void vReinit( const Eref& e, ProcPtr p ) = 0; - /** - * activation handles information coming from the SynHandler - * to the intFire. - */ - void activation( double val ); + /** + * activation handles information coming from the SynHandler + * to the intFire. + */ + void activation( double val ); - /// Message src for outgoing spikes. - static SrcFinfo1< double >* spikeOut(); + /// Message src for outgoing spikes. + static SrcFinfo1< double >* spikeOut(); - /** - * Initializes the class info. - */ - static const Cinfo* initCinfo(); - protected: - double threshold_; - double vReset_; - double activation_; - double refractT_; - double lastEvent_; - bool fired_; + /** + * Initializes the class info. + */ + static const Cinfo* initCinfo(); +protected: + double threshold_; + double vReset_; + double activation_; + double refractT_; + double lastEvent_; + bool fired_; }; } // namespace diff --git a/moose-core/intfire/LIF.cpp b/moose-core/intfire/LIF.cpp index 3812583acbd3bf30f69a096e70b8945bc127eee3..f1815ccde053449448896219c2c768b63eefda3c 100644 --- a/moose-core/intfire/LIF.cpp +++ b/moose-core/intfire/LIF.cpp @@ -7,8 +7,8 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" -#include "ElementValueFinfo.h" +#include "../basecode/header.h" +#include "../basecode/ElementValueFinfo.h" #include "../biophysics/CompartmentBase.h" #include "../biophysics/Compartment.h" #include "IntFireBase.h" @@ -18,23 +18,23 @@ using namespace moose; const Cinfo* LIF::initCinfo() { - static string doc[] = - { - "Name", "LIF", - "Author", "Upi Bhalla", - "Description", "Leaky Integrate-and-Fire neuron" - }; + static string doc[] = + { + "Name", "LIF", + "Author", "Upi Bhalla", + "Description", "Leaky Integrate-and-Fire neuron" + }; static Dinfo< LIF > dinfo; - static Cinfo lifCinfo( - "LIF", - IntFireBase::initCinfo(), - 0, 0, - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); + static Cinfo lifCinfo( + "LIF", + IntFireBase::initCinfo(), + 0, 0, + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); - return &lifCinfo; + return &lifCinfo; } static const Cinfo* lifCinfo = LIF::initCinfo(); @@ -44,10 +44,14 @@ static const Cinfo* lifCinfo = LIF::initCinfo(); ////////////////////////////////////////////////////////////////// LIF::LIF() -{;} +{ + ; +} LIF::~LIF() -{;} +{ + ; +} ////////////////////////////////////////////////////////////////// // LIF::Dest function definitions. @@ -55,37 +59,43 @@ LIF::~LIF() void LIF::vProcess( const Eref& e, ProcPtr p ) { - fired_ = false; - if ( p->currTime < lastEvent_ + refractT_ ) { - Vm_ = vReset_; - A_ = 0.0; - B_ = 1.0 / Rm_; - sumInject_ = 0.0; - VmOut()->send( e, Vm_ ); - } else { + fired_ = false; + if ( p->currTime < lastEvent_ + refractT_ ) + { + Vm_ = vReset_; + A_ = 0.0; + B_ = 1.0 / Rm_; + sumInject_ = 0.0; + VmOut()->send( e, Vm_ ); + } + else + { // activation can be a continous variable (graded synapse). // So integrate it at every time step, thus *dt. // For a delta-fn synapse, SynHandler-s divide by dt and send activation. // See: http://www.genesis-sim.org/GENESIS/Hyperdoc/Manual-26.html#synchan // for this continuous definition of activation. - Vm_ += activation_ * p->dt; - activation_ = 0.0; - if ( Vm_ > threshold_ ) { - Vm_ = vReset_; - lastEvent_ = p->currTime; - fired_ = true; - spikeOut()->send( e, p->currTime ); - VmOut()->send( e, Vm_ ); - } else { - Compartment::vProcess( e, p ); - } - } + Vm_ += activation_ * p->dt; + activation_ = 0.0; + if ( Vm_ > threshold_ ) + { + Vm_ = vReset_; + lastEvent_ = p->currTime; + fired_ = true; + spikeOut()->send( e, p->currTime ); + VmOut()->send( e, Vm_ ); + } + else + { + Compartment::vProcess( e, p ); + } + } } void LIF::vReinit( const Eref& e, ProcPtr p ) { - activation_ = 0.0; - fired_ = false; - lastEvent_ = -refractT_; // Allow it to fire right away. - Compartment::vReinit( e, p ); + activation_ = 0.0; + fired_ = false; + lastEvent_ = -refractT_; // Allow it to fire right away. + Compartment::vReinit( e, p ); } diff --git a/moose-core/intfire/LIF.h b/moose-core/intfire/LIF.h index 4b15f2c36082fa8dccec5121e1405d374b2de0e5..6bad50192924e1efec65e94c94075f1bb9aa3501 100644 --- a/moose-core/intfire/LIF.h +++ b/moose-core/intfire/LIF.h @@ -13,30 +13,32 @@ namespace moose { + /** * The IntFire class sets up an integrate-and-fire compartment. */ class LIF: public IntFireBase { - public: - LIF(); - virtual ~LIF(); - /** - * The process function does the object updating and sends out - * messages to channels, nernsts, and so on. - */ - void vProcess( const Eref& e, ProcPtr p ); +public: + LIF(); + virtual ~LIF(); + /** + * The process function does the object updating and sends out + * messages to channels, nernsts, and so on. + */ + void vProcess( const Eref& e, ProcPtr p ); - /** - * The reinit function reinitializes all fields. - */ - void vReinit( const Eref& e, ProcPtr p ); + /** + * The reinit function reinitializes all fields. + */ + void vReinit( const Eref& e, ProcPtr p ); - /** - * Initializes the class info. - */ - static const Cinfo* initCinfo(); + /** + * Initializes the class info. + */ + static const Cinfo* initCinfo(); }; + } #endif // _LIF_H diff --git a/moose-core/kinetics/BufPool.cpp b/moose-core/kinetics/BufPool.cpp index 54e183780a6f76fcb1614878e70e02981b28ae25..a980ffc1ef3d413eab0378c5537c0cfdc9b541bb 100644 --- a/moose-core/kinetics/BufPool.cpp +++ b/moose-core/kinetics/BufPool.cpp @@ -7,7 +7,7 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" +#include "../basecode/header.h" #include "PoolBase.h" #include "Pool.h" #include "BufPool.h" @@ -17,28 +17,28 @@ const Cinfo* BufPool::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions - ////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////// - // MsgDest Definitions - ////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////// - // SharedMsg Definitions - ////////////////////////////////////////////////////////////// - - static Dinfo< BufPool > dinfo; - static Cinfo bufPoolCinfo ( - "BufPool", - Pool::initCinfo(), - 0, - 0, - &dinfo - ); - - return &bufPoolCinfo; + ////////////////////////////////////////////////////////////// + // Field Definitions + ////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////// + // MsgDest Definitions + ////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////// + // SharedMsg Definitions + ////////////////////////////////////////////////////////////// + + static Dinfo< BufPool > dinfo; + static Cinfo bufPoolCinfo ( + "BufPool", + Pool::initCinfo(), + 0, + 0, + &dinfo + ); + + return &bufPoolCinfo; } ////////////////////////////////////////////////////////////// @@ -58,24 +58,24 @@ BufPool::~BufPool() void BufPool::vSetN( const Eref& e, double v ) { - Pool::vSetN( e, v ); - Pool::vSetNinit( e, v ); + Pool::vSetN( e, v ); + Pool::vSetNinit( e, v ); } void BufPool::vSetNinit( const Eref& e, double v ) { - vSetN( e, v ); + vSetN( e, v ); } void BufPool::vSetConc( const Eref& e, double conc ) { - double n = NA * conc * lookupVolumeFromMesh( e ); - vSetN( e, n ); + double n = NA * conc * lookupVolumeFromMesh( e ); + vSetN( e, n ); } void BufPool::vSetConcInit( const Eref& e, double conc ) { - vSetConc( e, conc ); + vSetConc( e, conc ); } ////////////////////////////////////////////////////////////// @@ -84,12 +84,12 @@ void BufPool::vSetConcInit( const Eref& e, double conc ) void BufPool::vProcess( const Eref& e, ProcPtr p ) { - Pool::vReinit( e, p ); + Pool::vReinit( e, p ); } void BufPool::vReinit( const Eref& e, ProcPtr p ) { - Pool::vReinit( e, p ); + Pool::vReinit( e, p ); } diff --git a/moose-core/kinetics/BufPool.h b/moose-core/kinetics/BufPool.h index 45b401e71bfab50b73d7730c22994b159e1f73eb..a0282d9beb7b2b67707b6fa8202eefad9ae6f1ed 100644 --- a/moose-core/kinetics/BufPool.h +++ b/moose-core/kinetics/BufPool.h @@ -12,28 +12,28 @@ class BufPool: public Pool { - public: - BufPool(); - ~BufPool(); +public: + BufPool(); + ~BufPool(); - ////////////////////////////////////////////////////////////////// - // Field assignment stuff - ////////////////////////////////////////////////////////////////// - /// The 'get' functions are simply inherited from Pool - void vSetN( const Eref& e, double v ); - void vSetNinit( const Eref& e, double v ); - void vSetConc( const Eref& e, double v ); - void vSetConcInit( const Eref& e, double v ); + ////////////////////////////////////////////////////////////////// + // Field assignment stuff + ////////////////////////////////////////////////////////////////// + /// The 'get' functions are simply inherited from Pool + void vSetN( const Eref& e, double v ); + void vSetNinit( const Eref& e, double v ); + void vSetConc( const Eref& e, double v ); + void vSetConcInit( const Eref& e, double v ); - ////////////////////////////////////////////////////////////////// - // Dest funcs - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // Dest funcs + ////////////////////////////////////////////////////////////////// - void vProcess( const Eref& e, ProcPtr p ); - void vReinit( const Eref& e, ProcPtr p ); + void vProcess( const Eref& e, ProcPtr p ); + void vReinit( const Eref& e, ProcPtr p ); - static const Cinfo* initCinfo(); - private: + static const Cinfo* initCinfo(); +private: }; #endif // _BUF_POOL_H diff --git a/moose-core/kinetics/Pool.cpp b/moose-core/kinetics/Pool.cpp index 8b0eb62940d7b361d6e3b9db3236a70e310aedb3..b6b448baaa89b2f93ac1d86da308f6c04251f2f4 100644 --- a/moose-core/kinetics/Pool.cpp +++ b/moose-core/kinetics/Pool.cpp @@ -7,8 +7,8 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" -#include "ElementValueFinfo.h" +#include "../basecode/header.h" +#include "../basecode/ElementValueFinfo.h" #include "lookupVolumeFromMesh.h" #include "PoolBase.h" #include "Pool.h" @@ -17,41 +17,41 @@ const Cinfo* Pool::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions: All inherited from PoolBase. - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // MsgDest Definitions: All inherited - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // SrcFinfo Definitions: All inherited. - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // SharedMsg Definitions: All inherited. - ////////////////////////////////////////////////////////////// - static Dinfo< Pool > dinfo; - static Cinfo poolCinfo ( - "Pool", - PoolBase::initCinfo(), - 0, - 0, - &dinfo - ); - - return &poolCinfo; + ////////////////////////////////////////////////////////////// + // Field Definitions: All inherited from PoolBase. + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // MsgDest Definitions: All inherited + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // SrcFinfo Definitions: All inherited. + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // SharedMsg Definitions: All inherited. + ////////////////////////////////////////////////////////////// + static Dinfo< Pool > dinfo; + static Cinfo poolCinfo ( + "Pool", + PoolBase::initCinfo(), + 0, + 0, + &dinfo + ); + + return &poolCinfo; } ////////////////////////////////////////////////////////////// // Class definitions ////////////////////////////////////////////////////////////// static const Cinfo* poolCinfo = Pool::initCinfo(); -const SrcFinfo1< double >& nOut = - *dynamic_cast< const SrcFinfo1< double >* >( - poolCinfo->findFinfo( "nOut" ) ); + +const SrcFinfo1< double >& nOut = *dynamic_cast<const SrcFinfo1< double >* + >(poolCinfo->findFinfo( "nOut")); Pool::Pool() - : n_( 0.0 ), nInit_( 0.0 ), diffConst_( 0.0 ), motorConst_( 0.0 ), - A_( 0.0 ), B_( 0.0 ), species_( 0 ) + : n_( 0.0 ), nInit_( 0.0 ), diffConst_( 0.0 ), motorConst_( 0.0 ), + A_( 0.0 ), B_( 0.0 ), species_( 0 ) {;} Pool::~Pool() @@ -67,22 +67,25 @@ Pool::~Pool() */ void Pool::vSetIsBuffered( const Eref& e, bool v ) { - static const Cinfo* bufPoolCinfo = Cinfo::find( "BufPool" ); - if (vGetIsBuffered( e ) == v) - return; - if (v) { - e.element()->replaceCinfo( bufPoolCinfo ); - } else { - e.element()->replaceCinfo( poolCinfo ); - } + static const Cinfo* bufPoolCinfo = Cinfo::find( "BufPool" ); + if (vGetIsBuffered( e ) == v) + return; + if (v) + { + e.element()->replaceCinfo( bufPoolCinfo ); + } + else + { + e.element()->replaceCinfo( poolCinfo ); + } } bool Pool::vGetIsBuffered( const Eref& e ) const { - /// We need this explicit check because when the moose class is - /// flipped, the internal C++ class isn't. - /// Inherited by BufPool. - return e.element()->cinfo()->name() == "BufPool"; + /// We need this explicit check because when the moose class is + /// flipped, the internal C++ class isn't. + /// Inherited by BufPool. + return e.element()->cinfo()->name() == "BufPool"; } ////////////////////////////////////////////////////////////// @@ -93,51 +96,54 @@ bool Pool::vGetIsBuffered( const Eref& e ) const void Pool::vProcess( const Eref& e, ProcPtr p ) { - // double A = e.sumBuf( aSlot ); - // double B = e.sumBuf( bSlot ); + // double A = e.sumBuf( aSlot ); + // double B = e.sumBuf( bSlot ); - if ( n_ > EPSILON && B_ > EPSILON ) { - double C = exp( -B_ * p->dt / n_ ); - n_ *= C + (A_ / B_ ) * ( 1.0 - C ); - } else { - n_ += ( A_ - B_ ) * p->dt; - if ( n_ < 0.0 ) - n_ = 0.0; - } + if ( n_ > EPSILON && B_ > EPSILON ) + { + double C = exp( -B_ * p->dt / n_ ); + n_ *= C + (A_ / B_ ) * ( 1.0 - C ); + } + else + { + n_ += ( A_ - B_ ) * p->dt; + if ( n_ < 0.0 ) + n_ = 0.0; + } - A_ = B_ = 0.0; + A_ = B_ = 0.0; - nOut.send( e, n_ ); + nOut.send( e, n_ ); } void Pool::vReinit( const Eref& e, ProcPtr p ) { - A_ = B_ = 0.0; - n_ = getNinit( e ); + A_ = B_ = 0.0; + n_ = getNinit( e ); - nOut.send( e, n_ ); + nOut.send( e, n_ ); } void Pool::vReac( double A, double B ) { - A_ += A; - B_ += B; + A_ += A; + B_ += B; } void Pool::vIncrement( double val ) { - if ( val > 0 ) - A_ += val; - else - B_ -= val; + if ( val > 0 ) + A_ += val; + else + B_ -= val; } void Pool::vDecrement( double val ) { - if ( val < 0 ) - A_ -= val; - else - B_ += val; + if ( val < 0 ) + A_ -= val; + else + B_ += val; } void Pool::vnIn( double val) @@ -149,7 +155,7 @@ void Pool::vnIn( double val) void Pool::vHandleMolWt( const Eref& e, double v ) { - ; // Here I should update DiffConst too. + ; // Here I should update DiffConst too. } ////////////////////////////////////////////////////////////// @@ -158,77 +164,77 @@ void Pool::vHandleMolWt( const Eref& e, double v ) void Pool::vSetN( const Eref& e, double v ) { - n_ = v; + n_ = v; } double Pool::vGetN( const Eref& e ) const { - return n_; + return n_; } void Pool::vSetNinit( const Eref& e, double v ) { - nInit_ = v; + nInit_ = v; } double Pool::vGetNinit( const Eref& e ) const { - return nInit_; + return nInit_; } // Conc is given in millimolar. Volume is in m^3 void Pool::vSetConc( const Eref& e, double c ) { - n_ = NA * c * lookupVolumeFromMesh( e ); + n_ = NA * c * lookupVolumeFromMesh( e ); } // Returns conc in millimolar. double Pool::vGetConc( const Eref& e ) const { - return (n_ / NA) / lookupVolumeFromMesh( e ); + return (n_ / NA) / lookupVolumeFromMesh( e ); } void Pool::vSetConcInit( const Eref& e, double c ) { - nInit_ = NA * c * lookupVolumeFromMesh( e ); + nInit_ = NA * c * lookupVolumeFromMesh( e ); } void Pool::vSetDiffConst( const Eref& e, double v ) { - diffConst_ = v; + diffConst_ = v; } double Pool::vGetDiffConst( const Eref& e ) const { - return diffConst_; + return diffConst_; } void Pool::vSetMotorConst( const Eref& e, double v ) { - motorConst_ = v; + motorConst_ = v; } double Pool::vGetMotorConst( const Eref& e ) const { - return motorConst_; + return motorConst_; } void Pool::vSetVolume( const Eref& e, double v ) { - cout << "Warning: Pool::vSetVolume: Operation not permitted. Ignored\n"; + cout << "Warning: Pool::vSetVolume: Operation not permitted. Ignored\n"; } double Pool::vGetVolume( const Eref& e ) const { - return lookupVolumeFromMesh( e ); + return lookupVolumeFromMesh( e ); } void Pool::vSetSpecies( const Eref& e, SpeciesId v ) { - species_ = v; + species_ = v; } SpeciesId Pool::vGetSpecies( const Eref& e ) const { - return species_; + return species_; } diff --git a/moose-core/kinetics/Pool.h b/moose-core/kinetics/Pool.h index bc4e88770a781fc67b59b2a6a6f442f4e32f46dd..51fbc5124570ba3e0e223b42e33dcc3fe0fd4a83 100644 --- a/moose-core/kinetics/Pool.h +++ b/moose-core/kinetics/Pool.h @@ -18,80 +18,80 @@ */ class Pool: public PoolBase { - public: - Pool(); - ~Pool(); +public: + Pool(); + ~Pool(); - ////////////////////////////////////////////////////////////////// - // Field assignment stuff. All override virtual funcs in the Pool - // base class. - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // Field assignment stuff. All override virtual funcs in the Pool + // base class. + ////////////////////////////////////////////////////////////////// - void vSetN( const Eref& e, double v ); - double vGetN( const Eref& e ) const; - void vSetNinit( const Eref& e, double v ); - double vGetNinit( const Eref& e ) const; - void vSetDiffConst( const Eref& e, double v ); - double vGetDiffConst( const Eref& e ) const; - void vSetMotorConst( const Eref& e, double v ); - double vGetMotorConst( const Eref& e ) const; + void vSetN( const Eref& e, double v ); + double vGetN( const Eref& e ) const; + void vSetNinit( const Eref& e, double v ); + double vGetNinit( const Eref& e ) const; + void vSetDiffConst( const Eref& e, double v ); + double vGetDiffConst( const Eref& e ) const; + void vSetMotorConst( const Eref& e, double v ); + double vGetMotorConst( const Eref& e ) const; - void vSetConc( const Eref& e, double v ); - double vGetConc( const Eref& e ) const; - void vSetConcInit( const Eref& e, double v ); - // double vGetConcInit( const Eref& e ) const; + void vSetConc( const Eref& e, double v ); + double vGetConc( const Eref& e ) const; + void vSetConcInit( const Eref& e, double v ); + // double vGetConcInit( const Eref& e ) const; - /** - * Volume is usually volume, but we also permit areal density - * This is obtained by looking up the corresponding spatial mesh - * entry in the parent compartment. If the message isn't set then - * it defaults to 1.0. - */ - void vSetVolume( const Eref& e, double v ); - double vGetVolume( const Eref& e ) const; + /** + * Volume is usually volume, but we also permit areal density + * This is obtained by looking up the corresponding spatial mesh + * entry in the parent compartment. If the message isn't set then + * it defaults to 1.0. + */ + void vSetVolume( const Eref& e, double v ); + double vGetVolume( const Eref& e ) const; - void vSetSpecies( const Eref& e, SpeciesId v ); - SpeciesId vGetSpecies( const Eref& e ) const; + void vSetSpecies( const Eref& e, SpeciesId v ); + SpeciesId vGetSpecies( const Eref& e ) const; - /** - * Functions to examine and change class between Pool and BufPool. - */ - void vSetIsBuffered( const Eref& e, bool v ); - bool vGetIsBuffered( const Eref& e) const; + /** + * Functions to examine and change class between Pool and BufPool. + */ + void vSetIsBuffered( const Eref& e, bool v ); + bool vGetIsBuffered( const Eref& e) const; - ////////////////////////////////////////////////////////////////// - // Dest funcs. These too override virtual funcs in the Pool base - // class. - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // Dest funcs. These too override virtual funcs in the Pool base + // class. + ////////////////////////////////////////////////////////////////// - void vHandleMolWt( const Eref& e, double v ); - void vProcess( const Eref& e, ProcPtr p ); - void vReinit( const Eref& e, ProcPtr p ); - void vReac( double A, double B ); - void vIncrement( double val ); - void vDecrement( double val ); - void vnIn( double val ); + void vHandleMolWt( const Eref& e, double v ); + void vProcess( const Eref& e, ProcPtr p ); + void vReinit( const Eref& e, ProcPtr p ); + void vReac( double A, double B ); + void vIncrement( double val ); + void vDecrement( double val ); + void vnIn( double val ); - ////////////////////////////////////////////////////////////////// - // Novel Dest funcs not present in Pool base class. - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // Novel Dest funcs not present in Pool base class. + ////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////// - static const Cinfo* initCinfo(); - private: - double n_; /// Number of molecules in pool - double nInit_; /// initial number of molecules. - double diffConst_; /// Diffusion constant - double motorConst_; /// Motor transport constant - double A_; /// Internal state variables, used only in explict mode - double B_; + ////////////////////////////////////////////////////////////////// + static const Cinfo* initCinfo(); +private: + double n_; /// Number of molecules in pool + double nInit_; /// initial number of molecules. + double diffConst_; /// Diffusion constant + double motorConst_; /// Motor transport constant + double A_; /// Internal state variables, used only in explict mode + double B_; - /** - * System wide identifier for all mol pools that are chemically - * the same species. - */ - unsigned int species_; + /** + * System wide identifier for all mol pools that are chemically + * the same species. + */ + unsigned int species_; }; #endif // _POOL_H diff --git a/moose-core/kinetics/PoolBase.cpp b/moose-core/kinetics/PoolBase.cpp index f1d7e0f44ba4984981c3a1b2f48e8fd6d0678843..b00153f4198897008e089b7b00109bee0c13cfc8 100644 --- a/moose-core/kinetics/PoolBase.cpp +++ b/moose-core/kinetics/PoolBase.cpp @@ -18,201 +18,205 @@ const SpeciesId DefaultSpeciesId = 0; const Cinfo* PoolBase::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions - ////////////////////////////////////////////////////////////// - static ElementValueFinfo< PoolBase, double > n( - "n", - "Number of molecules in pool", - &PoolBase::setN, - &PoolBase::getN - ); - - static ElementValueFinfo< PoolBase, double > nInit( - "nInit", - "Initial value of number of molecules in pool", - &PoolBase::setNinit, - &PoolBase::getNinit - ); - - static ElementValueFinfo< PoolBase, double > diffConst( - "diffConst", - "Diffusion constant of molecule", - &PoolBase::setDiffConst, - &PoolBase::getDiffConst - ); - - static ElementValueFinfo< PoolBase, double > motorConst( - "motorConst", - "Motor transport rate molecule. + is away from soma, - is " - "towards soma. Only relevant for ZombiePool subclasses.", - &PoolBase::setMotorConst, - &PoolBase::getMotorConst - ); - - static ElementValueFinfo< PoolBase, double > conc( - "conc", - "Concentration of molecules in this pool", - &PoolBase::setConc, - &PoolBase::getConc - ); - - static ElementValueFinfo< PoolBase, double > concInit( - "concInit", - "Initial value of molecular concentration in pool", - &PoolBase::setConcInit, - &PoolBase::getConcInit - ); - - static ElementValueFinfo< PoolBase, double > volume( - "volume", - "Volume of compartment. Units are SI. " - "Utility field, the actual volume info is " - "stored on a volume mesh entry in the parent compartment." - "This mapping is implicit: the parent compartment must be " - "somewhere up the element tree, and must have matching mesh " - "entries. If the compartment isn't" - "available the volume is just taken as 1", - &PoolBase::setVolume, - &PoolBase::getVolume - ); - - static ElementValueFinfo< PoolBase, unsigned int > speciesId( - "speciesId", - "Species identifier for this mol pool. Eventually link to ontology.", - &PoolBase::setSpecies, - &PoolBase::getSpecies - ); - - static ElementValueFinfo< PoolBase, bool > isBuffered( - "isBuffered", - "Flag: True if Pool is buffered. " - "In the case of Pool and BufPool the field can be assigned, to " - "change the type of the Pool object to BufPool, or vice versa. " - "None of the messages are affected. " - "This object class flip can only be done in the non-zombified " - "form of the Pool/BufPool. In Zombies it is read-only.", - &PoolBase::setIsBuffered, - &PoolBase::getIsBuffered - ); - - ////////////////////////////////////////////////////////////// - // MsgDest Definitions - ////////////////////////////////////////////////////////////// - static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< PoolBase >( &PoolBase::process ) ); - static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< PoolBase >( &PoolBase::reinit ) ); - - static DestFinfo reacDest( "reacDest", - "Handles reaction input", - new OpFunc2< PoolBase, double, double >( &PoolBase::reac ) - ); - - static DestFinfo handleMolWt( "handleMolWt", - "Separate finfo to assign molWt, and consequently diffusion const." - "Should only be used in SharedMsg with species.", - new EpFunc1< PoolBase, double >( &PoolBase::handleMolWt ) - ); - ////////////////////////////////////////////////////////////// - // MsgDest Definitions: These three are used for non-reaction - // calculations involving algebraically defined rate terms. - ////////////////////////////////////////////////////////////// - static DestFinfo increment( "increment", - "Increments mol numbers by specified amount. Can be +ve or -ve", - new OpFunc1< PoolBase, double >( &PoolBase::increment ) - ); - - static DestFinfo decrement( "decrement", - "Decrements mol numbers by specified amount. Can be +ve or -ve", - new OpFunc1< PoolBase, double >( &PoolBase::decrement ) - ); - - static DestFinfo nIn( "nIn", - "Assigns the number of molecules in Pool to specified value", - new OpFunc1< PoolBase, double >( &PoolBase::nIn ) - ); - - ////////////////////////////////////////////////////////////// - // SrcFinfo Definitions - ////////////////////////////////////////////////////////////// - - static SrcFinfo1< double > nOut( - "nOut", - "Sends out # of molecules in pool on each timestep" - ); - - static SrcFinfo0 requestMolWt( - "requestMolWt", - "Requests Species object for mol wt" - ); - - ////////////////////////////////////////////////////////////// - // SharedMsg Definitions - ////////////////////////////////////////////////////////////// - static Finfo* reacShared[] = { - &reacDest, &nOut - }; - static SharedFinfo reac( "reac", - "Connects to reaction", - reacShared, sizeof( reacShared ) / sizeof( const Finfo* ) - ); - static Finfo* procShared[] = { - &process, &reinit - }; - static SharedFinfo proc( "proc", - "Shared message for process and reinit", - procShared, sizeof( procShared ) / sizeof( const Finfo* ) - ); - - static Finfo* speciesShared[] = { - &requestMolWt, &handleMolWt - }; - - static SharedFinfo species( "species", - "Shared message for connecting to species objects", - speciesShared, sizeof( speciesShared ) / sizeof ( const Finfo* ) - ); - - static Finfo* poolFinfos[] = { - &n, // Value - &nInit, // Value - &diffConst, // Value - &motorConst, // Value - &conc, // Value - &concInit, // Value - &volume, // Readonly Value - &speciesId, // Value - &isBuffered, // Value - &increment, // DestFinfo - &decrement, // DestFinfo + ////////////////////////////////////////////////////////////// + // Field Definitions + ////////////////////////////////////////////////////////////// + static ElementValueFinfo< PoolBase, double > n( + "n", + "Number of molecules in pool", + &PoolBase::setN, + &PoolBase::getN + ); + + static ElementValueFinfo< PoolBase, double > nInit( + "nInit", + "Initial value of number of molecules in pool", + &PoolBase::setNinit, + &PoolBase::getNinit + ); + + static ElementValueFinfo< PoolBase, double > diffConst( + "diffConst", + "Diffusion constant of molecule", + &PoolBase::setDiffConst, + &PoolBase::getDiffConst + ); + + static ElementValueFinfo< PoolBase, double > motorConst( + "motorConst", + "Motor transport rate molecule. + is away from soma, - is " + "towards soma. Only relevant for ZombiePool subclasses.", + &PoolBase::setMotorConst, + &PoolBase::getMotorConst + ); + + static ElementValueFinfo< PoolBase, double > conc( + "conc", + "Concentration of molecules in this pool", + &PoolBase::setConc, + &PoolBase::getConc + ); + + static ElementValueFinfo< PoolBase, double > concInit( + "concInit", + "Initial value of molecular concentration in pool", + &PoolBase::setConcInit, + &PoolBase::getConcInit + ); + + static ElementValueFinfo< PoolBase, double > volume( + "volume", + "Volume of compartment. Units are SI. " + "Utility field, the actual volume info is " + "stored on a volume mesh entry in the parent compartment." + "This mapping is implicit: the parent compartment must be " + "somewhere up the element tree, and must have matching mesh " + "entries. If the compartment isn't" + "available the volume is just taken as 1", + &PoolBase::setVolume, + &PoolBase::getVolume + ); + + static ElementValueFinfo< PoolBase, unsigned int > speciesId( + "speciesId", + "Species identifier for this mol pool. Eventually link to ontology.", + &PoolBase::setSpecies, + &PoolBase::getSpecies + ); + + static ElementValueFinfo< PoolBase, bool > isBuffered( + "isBuffered", + "Flag: True if Pool is buffered. " + "In the case of Pool and BufPool the field can be assigned, to " + "change the type of the Pool object to BufPool, or vice versa. " + "None of the messages are affected. " + "This object class flip can only be done in the non-zombified " + "form of the Pool/BufPool. In Zombies it is read-only.", + &PoolBase::setIsBuffered, + &PoolBase::getIsBuffered + ); + + ////////////////////////////////////////////////////////////// + // MsgDest Definitions + ////////////////////////////////////////////////////////////// + static DestFinfo process( "process", + "Handles process call", + new ProcOpFunc< PoolBase >( &PoolBase::process ) ); + static DestFinfo reinit( "reinit", + "Handles reinit call", + new ProcOpFunc< PoolBase >( &PoolBase::reinit ) ); + + static DestFinfo reacDest( "reacDest", + "Handles reaction input", + new OpFunc2< PoolBase, double, double >( &PoolBase::reac ) + ); + + static DestFinfo handleMolWt( "handleMolWt", + "Separate finfo to assign molWt, and consequently diffusion const." + "Should only be used in SharedMsg with species.", + new EpFunc1< PoolBase, double >( &PoolBase::handleMolWt ) + ); + ////////////////////////////////////////////////////////////// + // MsgDest Definitions: These three are used for non-reaction + // calculations involving algebraically defined rate terms. + ////////////////////////////////////////////////////////////// + static DestFinfo increment( "increment", + "Increments mol numbers by specified amount. Can be +ve or -ve", + new OpFunc1< PoolBase, double >( &PoolBase::increment ) + ); + + static DestFinfo decrement( "decrement", + "Decrements mol numbers by specified amount. Can be +ve or -ve", + new OpFunc1< PoolBase, double >( &PoolBase::decrement ) + ); + + static DestFinfo nIn( "nIn", + "Assigns the number of molecules in Pool to specified value", + new OpFunc1< PoolBase, double >( &PoolBase::nIn ) + ); + + ////////////////////////////////////////////////////////////// + // SrcFinfo Definitions + ////////////////////////////////////////////////////////////// + + static SrcFinfo1< double > nOut( + "nOut", + "Sends out # of molecules in pool on each timestep" + ); + + static SrcFinfo0 requestMolWt( + "requestMolWt", + "Requests Species object for mol wt" + ); + + ////////////////////////////////////////////////////////////// + // SharedMsg Definitions + ////////////////////////////////////////////////////////////// + static Finfo* reacShared[] = + { + &reacDest, &nOut + }; + static SharedFinfo reac( "reac", + "Connects to reaction", + reacShared, sizeof( reacShared ) / sizeof( const Finfo* ) + ); + static Finfo* procShared[] = + { + &process, &reinit + }; + static SharedFinfo proc( "proc", + "Shared message for process and reinit", + procShared, sizeof( procShared ) / sizeof( const Finfo* ) + ); + + static Finfo* speciesShared[] = + { + &requestMolWt, &handleMolWt + }; + + static SharedFinfo species( "species", + "Shared message for connecting to species objects", + speciesShared, sizeof( speciesShared ) / sizeof ( const Finfo* ) + ); + + static Finfo* poolFinfos[] = + { + &n, // Value + &nInit, // Value + &diffConst, // Value + &motorConst, // Value + &conc, // Value + &concInit, // Value + &volume, // Readonly Value + &speciesId, // Value + &isBuffered, // Value + &increment, // DestFinfo + &decrement, // DestFinfo &nIn, // DestFinfo - &reac, // SharedFinfo - &proc, // SharedFinfo - &species, // SharedFinfo - }; - - static string doc[] = - { - "Name", "PoolBase", - "Author", "Upi Bhalla", - "Description", "Abstract base class for pools." - }; - static ZeroSizeDinfo< int > dinfo; - static Cinfo poolCinfo ( - "PoolBase", - Neutral::initCinfo(), - poolFinfos, - sizeof( poolFinfos ) / sizeof ( Finfo* ), - &dinfo, - doc, - sizeof( doc )/sizeof( string ), - true // Ban creation as this is an abstract base class. - ); - - return &poolCinfo; + &reac, // SharedFinfo + &proc, // SharedFinfo + &species, // SharedFinfo + }; + + static string doc[] = + { + "Name", "PoolBase", + "Author", "Upi Bhalla", + "Description", "Abstract base class for pools." + }; + static ZeroSizeDinfo< int > dinfo; + static Cinfo poolCinfo ( + "PoolBase", + Neutral::initCinfo(), + poolFinfos, + sizeof( poolFinfos ) / sizeof ( Finfo* ), + &dinfo, + doc, + sizeof( doc )/sizeof( string ), + true // Ban creation as this is an abstract base class. + ); + + return &poolCinfo; } ////////////////////////////////////////////////////////////// @@ -222,7 +226,7 @@ static const Cinfo* poolCinfo = PoolBase::initCinfo(); ////////////////////////////////////////////////////////////// PoolBase::PoolBase() - : concInit_( 0.0 ) + : concInit_( 0.0 ) {;} PoolBase::~PoolBase() @@ -234,37 +238,37 @@ PoolBase::~PoolBase() void PoolBase::process( const Eref& e, ProcPtr p ) { - vProcess( e, p ); + vProcess( e, p ); } void PoolBase::reinit( const Eref& e, ProcPtr p ) { - vReinit( e, p ); + vReinit( e, p ); } void PoolBase::increment( double val ) { - vIncrement(val); + vIncrement(val); } void PoolBase::decrement( double val ) { - vDecrement( val ); + vDecrement( val ); } void PoolBase::nIn( double val) { - vnIn(val); + vnIn(val); } void PoolBase::reac( double A, double B ) { - vReac( A, B ); + vReac( A, B ); } void PoolBase::handleMolWt( const Eref& e, double v ) { - vHandleMolWt( e, v ); + vHandleMolWt( e, v ); } ////////////////////////////////////////////////////////////// @@ -298,92 +302,92 @@ void PoolBase::vnIn( double val) void PoolBase::setN( const Eref& e, double v ) { - vSetN( e, v ); + vSetN( e, v ); } double PoolBase::getN( const Eref& e ) const { - return vGetN( e ); + return vGetN( e ); } void PoolBase::setNinit( const Eref& e, double v ) { - concInit_ = v / ( NA * lookupVolumeFromMesh( e ) ); - vSetNinit( e, v ); + concInit_ = v / ( NA * lookupVolumeFromMesh( e ) ); + vSetNinit( e, v ); } double PoolBase::getNinit( const Eref& e ) const { - return vGetNinit( e ); + return vGetNinit( e ); } // Conc is given in millimolar. Volume is in m^3 void PoolBase::setConc( const Eref& e, double c ) { - vSetConc( e, c ); + vSetConc( e, c ); } // Returns conc in millimolar. double PoolBase::getConc( const Eref& e ) const { - return vGetConc( e ); + return vGetConc( e ); } void PoolBase::setConcInit( const Eref& e, double c ) { - concInit_ = c; - vSetConcInit( e, c ); + concInit_ = c; + vSetConcInit( e, c ); } double PoolBase::vGetConcInit( const Eref& e ) const { - return concInit_; + return concInit_; } double PoolBase::getConcInit( const Eref& e ) const { - // return concInit_; - return vGetConcInit( e ); + // return concInit_; + return vGetConcInit( e ); } void PoolBase::setDiffConst( const Eref& e, double v ) { - vSetDiffConst( e, v ); + vSetDiffConst( e, v ); } double PoolBase::getDiffConst(const Eref& e ) const { - return vGetDiffConst( e ); + return vGetDiffConst( e ); } void PoolBase::setMotorConst( const Eref& e, double v ) { - vSetMotorConst( e, v ); + vSetMotorConst( e, v ); } double PoolBase::getMotorConst(const Eref& e ) const { - return vGetMotorConst( e ); + return vGetMotorConst( e ); } void PoolBase::setVolume( const Eref& e, double v ) { - vSetVolume( e, v ); + vSetVolume( e, v ); } double PoolBase::getVolume( const Eref& e ) const { - return vGetVolume( e ); + return vGetVolume( e ); } void PoolBase::setSpecies( const Eref& e, unsigned int v ) { - vSetSpecies( e, v ); + vSetSpecies( e, v ); } unsigned int PoolBase::getSpecies( const Eref& e ) const { - return vGetSpecies( e ); + return vGetSpecies( e ); } /** @@ -391,12 +395,12 @@ unsigned int PoolBase::getSpecies( const Eref& e ) const */ void PoolBase::setIsBuffered( const Eref& e, bool v ) { - vSetIsBuffered( e, v ); + vSetIsBuffered( e, v ); } bool PoolBase::getIsBuffered( const Eref& e ) const { - return vGetIsBuffered( e ); + return vGetIsBuffered( e ); } ////////////////////////////////////////////////////////////// @@ -409,7 +413,7 @@ void PoolBase::vSetMotorConst( const Eref& e, double v ) double PoolBase::vGetMotorConst(const Eref& e ) const { - return 0.0; + return 0.0; } /// Dummy default function for most pool subclasses. @@ -424,41 +428,43 @@ void PoolBase::vSetIsBuffered( const Eref& e, bool v ) ////////////////////////////////////////////////////////////// // static func void PoolBase::zombify( Element* orig, const Cinfo* zClass, - Id ksolve, Id dsolve ) + Id ksolve, Id dsolve ) { - if ( orig->cinfo() == zClass ) - return; - unsigned int start = orig->localDataStart(); - unsigned int num = orig->numLocalData(); - if ( num == 0 ) - return; - vector< unsigned int > species( num, 0 ); - vector< double > concInit( num, 0.0 ); - vector< double > diffConst( num, 0.0 ); - vector< double > motorConst( num, 0.0 ); - for ( unsigned int i = 0; i < num; ++i ) { - Eref er( orig, i + start ); - const PoolBase* pb = - reinterpret_cast< const PoolBase* >( er.data() ); - species[ i ] = pb->getSpecies( er ); - concInit[ i ] = pb->getConcInit( er ); - diffConst[ i ] = pb->getDiffConst( er ); - motorConst[ i ] = pb->getMotorConst( er ); - } - orig->zombieSwap( zClass ); - for ( unsigned int i = 0; i < num; ++i ) { - Eref er( orig, i + start ); - PoolBase* pb = reinterpret_cast< PoolBase* >( er.data() ); - pb->vSetSolver( ksolve, dsolve ); - pb->setSpecies( er, species[i] ); - pb->setConcInit( er, concInit[i] ); - pb->setDiffConst( er, diffConst[i] ); - pb->setMotorConst( er, motorConst[i] ); - } + if ( orig->cinfo() == zClass ) + return; + unsigned int start = orig->localDataStart(); + unsigned int num = orig->numLocalData(); + if ( num == 0 ) + return; + vector< unsigned int > species( num, 0 ); + vector< double > concInit( num, 0.0 ); + vector< double > diffConst( num, 0.0 ); + vector< double > motorConst( num, 0.0 ); + for ( unsigned int i = 0; i < num; ++i ) + { + Eref er( orig, i + start ); + const PoolBase* pb = + reinterpret_cast< const PoolBase* >( er.data() ); + species[ i ] = pb->getSpecies( er ); + concInit[ i ] = pb->getConcInit( er ); + diffConst[ i ] = pb->getDiffConst( er ); + motorConst[ i ] = pb->getMotorConst( er ); + } + orig->zombieSwap( zClass ); + for ( unsigned int i = 0; i < num; ++i ) + { + Eref er( orig, i + start ); + PoolBase* pb = reinterpret_cast< PoolBase* >( er.data() ); + pb->vSetSolver( ksolve, dsolve ); + pb->setSpecies( er, species[i] ); + pb->setConcInit( er, concInit[i] ); + pb->setDiffConst( er, diffConst[i] ); + pb->setMotorConst( er, motorConst[i] ); + } } // Virtual func: default does nothing. void PoolBase::vSetSolver( Id ksolve, Id dsolve ) { - ; + ; } diff --git a/moose-core/kinetics/PoolBase.h b/moose-core/kinetics/PoolBase.h index b5aaa1b8d545e363f1c413786ba7c73b5ada9400..20ab0000eaf6b62092a65bc58104176285ca1edb 100644 --- a/moose-core/kinetics/PoolBase.h +++ b/moose-core/kinetics/PoolBase.h @@ -29,134 +29,134 @@ extern const SpeciesId DefaultSpeciesId; */ class PoolBase { - friend void testSyncArray( unsigned int size, unsigned int numThreads, - unsigned int method ); - friend void checkVal( double time, const PoolBase* m, unsigned int size ); - friend void forceCheckVal( double time, Element* e, unsigned int size ); - - public: - PoolBase(); - virtual ~PoolBase(); - - ////////////////////////////////////////////////////////////////// - // Field assignment stuff: Interface for the Cinfo, hence regular - // funcs. These internally call the virtual funcs that do the real - // work. - ////////////////////////////////////////////////////////////////// - void setN( const Eref& e, double v ); - double getN( const Eref& e ) const; - void setNinit( const Eref& e, double v ); - double getNinit( const Eref& e ) const; - void setDiffConst( const Eref& e, double v ); - double getDiffConst( const Eref& e ) const; - void setMotorConst( const Eref& e, double v ); - double getMotorConst( const Eref& e ) const; - - void setConc( const Eref& e, double v ); - double getConc( const Eref& e ) const; - void setConcInit( const Eref& e, double v ); - double getConcInit( const Eref& e ) const; - - /** - * Volume is usually volume, but we also permit areal density - * This is obtained by looking up the corresponding spatial mesh - * entry in the parent compartment. If the message isn't set then - * it defaults to 1.0. - */ - void setVolume( const Eref& e, double v ); - double getVolume( const Eref& e ) const; - - void setSpecies( const Eref& e, SpeciesId v ); - SpeciesId getSpecies( const Eref& e ) const; - /** - * Functions to examine and change class between Pool and BufPool. - */ - void setIsBuffered( const Eref& e, bool v ); - bool getIsBuffered( const Eref& e ) const; - - ////////////////////////////////////////////////////////////////// - // Here are the inner virtual funcs for fields. - // All these are pure virtual - ////////////////////////////////////////////////////////////////// - - virtual void vSetN( const Eref& e, double v ) = 0; - virtual double vGetN( const Eref& e ) const = 0; - virtual void vSetNinit( const Eref& e, double v ) = 0; - virtual double vGetNinit( const Eref& e ) const = 0; - virtual void vSetDiffConst( const Eref& e, double v ) = 0; - virtual double vGetDiffConst( const Eref& e ) const = 0; - virtual void vSetMotorConst( const Eref& e, double v ); - virtual double vGetMotorConst( const Eref& e ) const; - - virtual void vSetConc( const Eref& e, double v ) = 0; - virtual double vGetConc( const Eref& e ) const = 0; - virtual void vSetConcInit( const Eref& e, double v ) = 0; - virtual double vGetConcInit( const Eref& e ) const; - virtual double vGetVolume( const Eref& e ) const = 0; - virtual void vSetVolume( const Eref& e, double v ) = 0; - virtual void vSetSpecies( const Eref& e, SpeciesId v ) = 0; - virtual SpeciesId vGetSpecies( const Eref& e ) const = 0; - /// I put in a default empty function for vSetIsBuffered. - virtual void vSetIsBuffered( const Eref& e, bool v ); - virtual bool vGetIsBuffered( const Eref& e) const = 0; - /** - * Assign whatever info is needed by the zombie based on the - * solver Element. Encapsulates some unpleasant field extraction, - * casting, and assignment. Default version of this function does - * nothing. - */ - virtual void vSetSolver( Id ksolve, Id dsolve ); - - ////////////////////////////////////////////////////////////////// - /** - * zombify is the base function for conversion between pool - * subclasses. This can be overridden, but should work for most - * things. This takes the original Element, and without touching - * its messaging, replaces it with a new data object of the - * specified zClass. It does the best it can with conversion of - * fields. Typically needs to be followed by rescheduling and - * possibly a class-specific function for assigning further - * zombie fields outside the ken of the PoolBase. - * The 'solver' argument specifies which objects handle the solver - * for this conversion. For the Pool this is either or both of - * a kinetic solver /ksolve/ and a diffusion solver /dsolve/. - * The term zombie arises because this operation was originally - * carried out to strip an object of independent function, and - * replace it with a solver-controlled facsimile. - */ - static void zombify( Element* original, const Cinfo* zClass, - Id ksolve, Id dsolve ); - - ////////////////////////////////////////////////////////////////// - // Dest funcs - ////////////////////////////////////////////////////////////////// - void process( const Eref& e, ProcPtr p ); - void reinit( const Eref& e, ProcPtr p ); - void reac( double A, double B ); - void handleMolWt( const Eref& e, double v ); - void increment( double val ); - void decrement( double val ); - void nIn( double val ); - - ////////////////////////////////////////////////////////////////// - // Virtual Dest funcs. Most of these have a generic do-nothing - // function here, as most of the derived classes don't need to - // do anything. - ////////////////////////////////////////////////////////////////// - virtual void vProcess( const Eref& e, ProcPtr p ); - virtual void vReinit( const Eref& e, ProcPtr p ); - virtual void vReac( double A, double B ); - virtual void vHandleMolWt( const Eref& e, double v); - virtual void vIncrement( double val ); - virtual void vDecrement( double val ); - virtual void vnIn( double val ); - - ////////////////////////////////////////////////////////////////// - static const Cinfo* initCinfo(); - private: - double concInit_; /// Initial concentration. - // We don't store the conc here as this is computed on the fly - // by derived classes. But the PoolBase::concInit is authoritative. + friend void testSyncArray( unsigned int size, unsigned int numThreads, + unsigned int method ); + friend void checkVal( double time, const PoolBase* m, unsigned int size ); + friend void forceCheckVal( double time, Element* e, unsigned int size ); + +public: + PoolBase(); + virtual ~PoolBase(); + + ////////////////////////////////////////////////////////////////// + // Field assignment stuff: Interface for the Cinfo, hence regular + // funcs. These internally call the virtual funcs that do the real + // work. + ////////////////////////////////////////////////////////////////// + void setN( const Eref& e, double v ); + double getN( const Eref& e ) const; + void setNinit( const Eref& e, double v ); + double getNinit( const Eref& e ) const; + void setDiffConst( const Eref& e, double v ); + double getDiffConst( const Eref& e ) const; + void setMotorConst( const Eref& e, double v ); + double getMotorConst( const Eref& e ) const; + + void setConc( const Eref& e, double v ); + double getConc( const Eref& e ) const; + void setConcInit( const Eref& e, double v ); + double getConcInit( const Eref& e ) const; + + /** + * Volume is usually volume, but we also permit areal density + * This is obtained by looking up the corresponding spatial mesh + * entry in the parent compartment. If the message isn't set then + * it defaults to 1.0. + */ + void setVolume( const Eref& e, double v ); + double getVolume( const Eref& e ) const; + + void setSpecies( const Eref& e, SpeciesId v ); + SpeciesId getSpecies( const Eref& e ) const; + /** + * Functions to examine and change class between Pool and BufPool. + */ + void setIsBuffered( const Eref& e, bool v ); + bool getIsBuffered( const Eref& e ) const; + + ////////////////////////////////////////////////////////////////// + // Here are the inner virtual funcs for fields. + // All these are pure virtual + ////////////////////////////////////////////////////////////////// + + virtual void vSetN( const Eref& e, double v ) = 0; + virtual double vGetN( const Eref& e ) const = 0; + virtual void vSetNinit( const Eref& e, double v ) = 0; + virtual double vGetNinit( const Eref& e ) const = 0; + virtual void vSetDiffConst( const Eref& e, double v ) = 0; + virtual double vGetDiffConst( const Eref& e ) const = 0; + virtual void vSetMotorConst( const Eref& e, double v ); + virtual double vGetMotorConst( const Eref& e ) const; + + virtual void vSetConc( const Eref& e, double v ) = 0; + virtual double vGetConc( const Eref& e ) const = 0; + virtual void vSetConcInit( const Eref& e, double v ) = 0; + virtual double vGetConcInit( const Eref& e ) const; + virtual double vGetVolume( const Eref& e ) const = 0; + virtual void vSetVolume( const Eref& e, double v ) = 0; + virtual void vSetSpecies( const Eref& e, SpeciesId v ) = 0; + virtual SpeciesId vGetSpecies( const Eref& e ) const = 0; + /// I put in a default empty function for vSetIsBuffered. + virtual void vSetIsBuffered( const Eref& e, bool v ); + virtual bool vGetIsBuffered( const Eref& e) const = 0; + /** + * Assign whatever info is needed by the zombie based on the + * solver Element. Encapsulates some unpleasant field extraction, + * casting, and assignment. Default version of this function does + * nothing. + */ + virtual void vSetSolver( Id ksolve, Id dsolve ); + + ////////////////////////////////////////////////////////////////// + /** + * zombify is the base function for conversion between pool + * subclasses. This can be overridden, but should work for most + * things. This takes the original Element, and without touching + * its messaging, replaces it with a new data object of the + * specified zClass. It does the best it can with conversion of + * fields. Typically needs to be followed by rescheduling and + * possibly a class-specific function for assigning further + * zombie fields outside the ken of the PoolBase. + * The 'solver' argument specifies which objects handle the solver + * for this conversion. For the Pool this is either or both of + * a kinetic solver /ksolve/ and a diffusion solver /dsolve/. + * The term zombie arises because this operation was originally + * carried out to strip an object of independent function, and + * replace it with a solver-controlled facsimile. + */ + static void zombify( Element* original, const Cinfo* zClass, + Id ksolve, Id dsolve ); + + ////////////////////////////////////////////////////////////////// + // Dest funcs + ////////////////////////////////////////////////////////////////// + void process( const Eref& e, ProcPtr p ); + void reinit( const Eref& e, ProcPtr p ); + void reac( double A, double B ); + void handleMolWt( const Eref& e, double v ); + void increment( double val ); + void decrement( double val ); + void nIn( double val ); + + ////////////////////////////////////////////////////////////////// + // Virtual Dest funcs. Most of these have a generic do-nothing + // function here, as most of the derived classes don't need to + // do anything. + ////////////////////////////////////////////////////////////////// + virtual void vProcess( const Eref& e, ProcPtr p ); + virtual void vReinit( const Eref& e, ProcPtr p ); + virtual void vReac( double A, double B ); + virtual void vHandleMolWt( const Eref& e, double v); + virtual void vIncrement( double val ); + virtual void vDecrement( double val ); + virtual void vnIn( double val ); + + ////////////////////////////////////////////////////////////////// + static const Cinfo* initCinfo(); +private: + double concInit_; /// Initial concentration. + // We don't store the conc here as this is computed on the fly + // by derived classes. But the PoolBase::concInit is authoritative. }; #endif // _POOL_BASE_H diff --git a/moose-core/kinetics/ReadKkit.cpp b/moose-core/kinetics/ReadKkit.cpp index 8172ae90920e225ab8337be73316c1bd0cdca1a8..1a2e0776494a67175496e71e68a5004ddc6b2ace 100644 --- a/moose-core/kinetics/ReadKkit.cpp +++ b/moose-core/kinetics/ReadKkit.cpp @@ -228,13 +228,13 @@ void setMethod( Shell* s, Id mgr, double simdt, double plotdt, string simpath2 = mgr.path() + "/##[ISA=StimulusTable]," + mgr.path() + "/##[ISA=PulseGen]"; string m = lower( method ); - + /* if ( m == "ksolve" || m =="gsl" || m == "gssa" || m == "gsolve" || m == "gillespie" || m == "stochastic" ) { cout << " Warning: Default solver set is Exponential Euler. To set \'gsl\' or \'gssa\' solver use function mooseaddChemSolver(modelpath,\'solverType\')"<<"\n"; } - /* + if ( m == "rk4" ) { cout << "Warning, not yet implemented. Using rk5 instead\n"; @@ -312,7 +312,7 @@ Id ReadKkit::read( assert(kinetics != Id()); Id cInfo = s->doCreate( "Annotator", basePath_, "info", 1 ); assert( cInfo != Id() ); - Field< string > ::set(cInfo, "solver", method); + Field< string > ::set(cInfo, "solver", "ee"); Field< double > ::set(cInfo, "runtime", maxtime_); s->doReinit(); return mgr; @@ -578,6 +578,8 @@ void ReadKkit::objdump( const vector< string >& args) assignArgs( tableMap_, args ); else if ( args[1] == "stim" ) assignArgs( stimMap_, args ); + else if ( args[1] == "kchan" ) + assignArgs( chanMap_, args ); } void ReadKkit::call( const vector< string >& args) @@ -1185,9 +1187,11 @@ Id ReadKkit::buildChan( const vector< string >& args ) Id pa = shell_->doFind( head ).id; assert( pa != Id() ); - cout << "Warning: Kchan not yet supported in MOOSE, creating dummy:\n" - << " " << clean << "\n"; - Id chan = shell_->doCreate( "Neutral", pa, tail, 1 ); + // cout << "Warning: Kchan not yet supported in MOOSE, creating dummy:\n" << " " << clean << "\n"; + // + double permeability = atof( args[ chanMap_["perm"] ].c_str() ); + Id chan = shell_->doCreate( "ConcChan", pa, tail, 1 ); + Field< double >::set( chan, "permeability", permeability ); assert( chan != Id() ); string chanPath = clean.substr( 10 ); chanIds_[ chanPath ] = chan; @@ -1346,16 +1350,14 @@ void ReadKkit::addmsg( const vector< string >& args) if ( args[3] == "REAC" ) { if ( args[4] == "A" && args[5] == "B" ) { - // Ignore kchans if ( chanIds_.find( src ) != chanIds_.end() ) - ; // found a kchan, do nothing + innerAddMsg( src, chanIds_, "in", dest, poolIds_, "reac"); else innerAddMsg( src, reacIds_, "sub", dest, poolIds_, "reac"); } else if ( args[4] == "B" && args[5] == "A" ) { - // Ignore kchans if ( chanIds_.find( src ) != chanIds_.end() ) - ; // found a kchan, do nothing + innerAddMsg( src, chanIds_, "out", dest, poolIds_, "reac"); else // dest pool is product of src reac innerAddMsg( src, reacIds_, "prd", dest, poolIds_, "reac"); @@ -1387,6 +1389,10 @@ void ReadKkit::addmsg( const vector< string >& args) else innerAddMsg( src, mmEnzIds_, "prd", dest, poolIds_, "reac" ); } + else if ( args[3] == "NUMCHAN" ) { // Msg from chan pool to concchan + if ( chanIds_.find( dest ) != chanIds_.end() ) + innerAddMsg( src, poolIds_, "nOut", dest, chanIds_, "setNumChan"); + } else if ( args[3] == "PLOT" ) { // Time-course output for pool string head; string temp; diff --git a/moose-core/kinetics/ReadKkit.h b/moose-core/kinetics/ReadKkit.h index 8e171fc64fa9de30df7781227abf4cdd2fa141b4..1dae27bfacc1cb33cb36ccda199502e67c524c11 100644 --- a/moose-core/kinetics/ReadKkit.h +++ b/moose-core/kinetics/ReadKkit.h @@ -217,6 +217,7 @@ class ReadKkit map< string, int > groupMap_; map< string, int > tableMap_; map< string, int > stimMap_; + map< string, int > chanMap_; map< string, Id > poolIds_; map< string, Id > reacIds_; map< string, Id > enzIds_; diff --git a/moose-core/kinetics/WriteKkit.cpp b/moose-core/kinetics/WriteKkit.cpp index c32b1fa024b8b7f0a03fecc6da05ff5f5855607c..3c3bc890afa1dbac1f5022bfc457ad1eefcbce52 100644 --- a/moose-core/kinetics/WriteKkit.cpp +++ b/moose-core/kinetics/WriteKkit.cpp @@ -26,255 +26,268 @@ void writeHeader( ofstream& fout, - double simdt, double plotdt, double maxtime, double defaultVol) + double simdt, double plotdt, double maxtime, double defaultVol) { - time_t rawtime; - time( &rawtime ); - - fout << - "//genesis\n" - "// kkit Version 11 flat dumpfile\n\n"; - fout << "// Saved on " << ctime( &rawtime ) << endl; - fout << "include kkit {argv 1}\n"; - fout << "FASTDT = " << simdt << endl; - fout << "SIMDT = " << simdt << endl; - fout << "CONTROLDT = " << plotdt << endl; - fout << "PLOTDT = " << plotdt << endl; - fout << "MAXTIME = " << maxtime << endl; - fout << "TRANSIENT_TIME = 2\n" - "VARIABLE_DT_FLAG = 0\n"; - fout << "DEFAULT_VOL = " << defaultVol << endl; - fout << "VERSION = 11.0\n" - "setfield /file/modpath value ~/scripts/modules\n" - "kparms\n\n"; - - fout << - "initdump -version 3 -ignoreorphans 1\n" - "simobjdump table input output alloced step_mode stepsize x y z\n" - "simobjdump xtree path script namemode sizescale\n" - "simobjdump xcoredraw xmin xmax ymin ymax\n" - "simobjdump xtext editable\n" - "simobjdump xgraph xmin xmax ymin ymax overlay\n" - "simobjdump xplot pixflags script fg ysquish do_slope wy\n" - "simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \\\n" - " link savename file version md5sum mod_save_flag x y z\n" - "simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y z\n" - "simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \\\n" - " geomname xtree_fg_req xtree_textfg_req x y z\n" - "simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z\n" - "simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \\\n" - " keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z\n" - "simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \\\n" - " trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z\n" - "simobjdump xtab input output alloced step_mode stepsize notes editfunc \\\n" - " xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z\n" - "simobjdump kchan perm gmax Vm is_active use_nernst notewriteReacs xtree_fg_req \\\n" - " xtree_textfg_req x y z\n" - "simobjdump transport input output alloced step_mode stepsize dt delay clock \\\n" - " kf xtree_fg_req xtree_textfg_req x y z\n" - "simobjdump proto x y z\n"; - //"simundump geometry /kinetics/geometry 0 1.6667e-19 3 sphere \"\" white black 0 0 0\n\n"; + time_t rawtime; + time( &rawtime ); + + fout << + "//genesis\n" + "// kkit Version 11 flat dumpfile\n\n"; + fout << "// Saved on " << ctime( &rawtime ) << endl; + fout << "include kkit {argv 1}\n"; + fout << "FASTDT = " << simdt << endl; + fout << "SIMDT = " << simdt << endl; + fout << "CONTROLDT = " << plotdt << endl; + fout << "PLOTDT = " << plotdt << endl; + fout << "MAXTIME = " << maxtime << endl; + fout << "TRANSIENT_TIME = 2\n" + "VARIABLE_DT_FLAG = 0\n"; + fout << "DEFAULT_VOL = " << defaultVol << endl; + fout << "VERSION = 11.0\n" + "setfield /file/modpath value ~/scripts/modules\n" + "kparms\n\n"; + + fout << + "initdump -version 3 -ignoreorphans 1\n" + "simobjdump table input output alloced step_mode stepsize x y z\n" + "simobjdump xtree path script namemode sizescale\n" + "simobjdump xcoredraw xmin xmax ymin ymax\n" + "simobjdump xtext editable\n" + "simobjdump xgraph xmin xmax ymin ymax overlay\n" + "simobjdump xplot pixflags script fg ysquish do_slope wy\n" + "simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \\\n" + " link savename file version md5sum mod_save_flag x y z\n" + "simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y z\n" + "simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \\\n" + " geomname xtree_fg_req xtree_textfg_req x y z\n" + "simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z\n" + "simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \\\n" + " keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z\n" + "simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \\\n" + " trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z\n" + "simobjdump xtab input output alloced step_mode stepsize notes editfunc \\\n" + " xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z\n" + "simobjdump kchan perm gmax Vm is_active use_nernst notewriteReacs xtree_fg_req \\\n" + " xtree_textfg_req x y z\n" + "simobjdump transport input output alloced step_mode stepsize dt delay clock \\\n" + " kf xtree_fg_req xtree_textfg_req x y z\n" + "simobjdump proto x y z\n"; + //"simundump geometry /kinetics/geometry 0 1.6667e-19 3 sphere \"\" white black 0 0 0\n\n"; } string trimPath(Id id, Id comptid) { - string msgpath = Field <string> :: get(id,"path"); - ObjId compartment(msgpath); - string path1; - cout << " trimpath " << msgpath <<endl; - // triming the string compartment Level - while( Field<string>::get(compartment,"className") != "CubeMesh" - && Field<string>::get(compartment,"className") != "CylMesh" - ) - compartment = Field<ObjId> :: get(compartment, "parent"); - string cmpt = Field < string > :: get(compartment,"name"); - if (cmpt != "kinetics") - { std::size_t found = msgpath.find(cmpt); - if (found !=std::string::npos) - path1 = msgpath.substr(found-1,msgpath.length()); - else - { - path1 = msgpath; - - } - } - else - { std :: size_t found = msgpath.find(cmpt); - if (found !=std::string::npos) - { string pathC = msgpath.substr(found-1,msgpath.length()); - std :: size_t slash = pathC.find('/',found); - if (slash !=std::string::npos) - path1 = pathC.substr(slash,pathC.length()); - else - { path1 = msgpath; - } - } - } - cout << " path " << path1 << endl; - return path1; + string msgpath = Field <string> :: get(id,"path"); + ObjId compartment(msgpath); + string path1; + cout << " trimpath " << msgpath <<endl; + // triming the string compartment Level + while( Field<string>::get(compartment,"className") != "CubeMesh" + && Field<string>::get(compartment,"className") != "CylMesh" + ) + compartment = Field<ObjId> :: get(compartment, "parent"); + string cmpt = Field < string > :: get(compartment,"name"); + if (cmpt != "kinetics") + { + std::size_t found = msgpath.find(cmpt); + if (found !=std::string::npos) + path1 = msgpath.substr(found-1,msgpath.length()); + else + { + path1 = msgpath; + } + } + else + { + std :: size_t found = msgpath.find(cmpt); + if (found !=std::string::npos) + { + string pathC = msgpath.substr(found-1,msgpath.length()); + std :: size_t slash = pathC.find('/',found); + if (slash !=std::string::npos) + path1 = pathC.substr(slash,pathC.length()); + else + { + path1 = msgpath; + } + } + } + cout << " path " << path1 << endl; + return path1; } Id getEnzCplx( Id id ) { - vector < Id > srct = LookupField <string,vector < Id> >::get(id, "neighbors","cplxDest"); - return srct[0]; + vector < Id > srct = LookupField <string,vector < Id> >::get(id, "neighbors","cplxDest"); + return srct[0]; } Id getEnzMol( Id id ) { - vector < Id > srct = LookupField <string,vector < Id> >::get(id, "neighbors","enzDest"); - return srct[0]; + vector < Id > srct = LookupField <string,vector < Id> >::get(id, "neighbors","enzDest"); + return srct[0]; } void writeEnz( ofstream& fout, Id id, - string colour, string textcolour, - double x, double y, Id comptid ) + string colour, string textcolour, + double x, double y, Id comptid ) { - string path = id.path(); - string comptname = Field < string > :: get(comptid,"name"); - string poolpath = trimPath(id,comptid); - - - double k1 = 0; - double k2 = 0; - double k3 = 0; - double nInit = 0; - double concInit = 0; - double n = 0; - double conc = 0; - Id enzMol = getEnzMol( id ); - assert( enzMol != Id() ); - double vol = Field< double >::get( enzMol, "volume" ) * NA * 1e-3; - unsigned int isMichaelisMenten = 0; - string enzClass = Field < string > :: get(id,"className"); - if (enzClass == "ZombieMMenz" or enzClass == "MMenz") - { k1 = Field < double > :: get (id,"numKm"); - k3 = Field < double > :: get (id,"kcat"); - k2 = 4.0*k3; - k1 = (k2 + k3) / k1; - isMichaelisMenten = 1; - } - else if (enzClass == "ZombieEnz" or enzClass == "Enz") - { k1 = Field< double >::get( id, "k1" ); - k2 = Field< double >::get( id, "k2" ); - k3 = Field< double >::get( id, "k3" ); - Id cplx = getEnzCplx( id ); - assert( cplx != Id() ); - nInit = Field< double >::get( cplx, "nInit" ); - n = Field< double >::get( cplx, "n" ); - concInit = Field< double >::get( cplx, "concInit" ); - conc = Field< double >::get( cplx, "conc" ); - } - fout << "simundump kenz /kinetics" << poolpath << " 0 " << - concInit << " " << - conc << " " << - nInit << " " << - n << " " << - vol << " " << - k1 << " " << - k2 << " " << - k3 << " " << - 0 << " " << - isMichaelisMenten << " " << - "\"\"" << " " << - colour << " " << textcolour << " \"\"" << - " " << x << " " << y << " 0\n"; + string path = id.path(); + string comptname = Field < string > :: get(comptid,"name"); + string poolpath = trimPath(id,comptid); + + + double k1 = 0; + double k2 = 0; + double k3 = 0; + double nInit = 0; + double concInit = 0; + double n = 0; + double conc = 0; + Id enzMol = getEnzMol( id ); + assert( enzMol != Id() ); + double vol = Field< double >::get( enzMol, "volume" ) * NA * 1e-3; + unsigned int isMichaelisMenten = 0; + string enzClass = Field < string > :: get(id,"className"); + if (enzClass == "ZombieMMenz" or enzClass == "MMenz") + { + k1 = Field < double > :: get (id,"numKm"); + k3 = Field < double > :: get (id,"kcat"); + k2 = 4.0*k3; + k1 = (k2 + k3) / k1; + isMichaelisMenten = 1; + } + else if (enzClass == "ZombieEnz" or enzClass == "Enz") + { + k1 = Field< double >::get( id, "k1" ); + k2 = Field< double >::get( id, "k2" ); + k3 = Field< double >::get( id, "k3" ); + Id cplx = getEnzCplx( id ); + assert( cplx != Id() ); + nInit = Field< double >::get( cplx, "nInit" ); + n = Field< double >::get( cplx, "n" ); + concInit = Field< double >::get( cplx, "concInit" ); + conc = Field< double >::get( cplx, "conc" ); + } + fout << "simundump kenz /kinetics" << poolpath << " 0 " << + concInit << " " << + conc << " " << + nInit << " " << + n << " " << + vol << " " << + k1 << " " << + k2 << " " << + k3 << " " << + 0 << " " << + isMichaelisMenten << " " << + "\"\"" << " " << + colour << " " << textcolour << " \"\"" << + " " << x << " " << y << " 0\n"; } void writeReac( ofstream& fout, Id id, - string colour, string textcolour, - double x, double y, Id comptid ) + string colour, string textcolour, + double x, double y, Id comptid ) { - string reacPar = Field <string> :: get(comptid,"name"); - string reacname = Field<string> :: get(id, "name"); - double kf = Field< double >::get( id, "numKf" ); - double kb = Field< double >::get( id, "numKb" ); - - unsigned int numSub = - Field< unsigned int >::get( id, "numSubstrates" ); - unsigned int numPrd = - Field< unsigned int >::get( id, "numProducts" ); - fout << "simundump kreac /kinetics" << trimPath(id,comptid) << " 0 " << - kf << " " << kb << " \"\" " << - colour << " " << textcolour << " " << x << " " << y << " 0\n"; + string reacPar = Field <string> :: get(comptid,"name"); + string reacname = Field<string> :: get(id, "name"); + double kf = Field< double >::get( id, "numKf" ); + double kb = Field< double >::get( id, "numKb" ); + + unsigned int numSub = + Field< unsigned int >::get( id, "numSubstrates" ); + unsigned int numPrd = + Field< unsigned int >::get( id, "numProducts" ); + fout << "simundump kreac /kinetics" << trimPath(id,comptid) << " 0 " << + kf << " " << kb << " \"\" " << + colour << " " << textcolour << " " << x << " " << y << " 0\n"; } unsigned int getSlaveEnable( Id id ) { - static const Finfo* setNinitFinfo = - PoolBase::initCinfo()->findFinfo( "set_nInit" ); - static const Finfo* setConcInitFinfo = - PoolBase::initCinfo()->findFinfo( "set_concInit" ); - unsigned int ret = 0; - vector< Id > src; - if ( id.element()->cinfo()->isA( "BufPool" ) ) { - if ( id.element()->getNeighbors( src, setConcInitFinfo ) > 0 ) { - ret = 2; - } else if ( id.element()->getNeighbors( src, setNinitFinfo ) > 0 ){ - ret = 4; - } - } else { - return 0; - } - if ( ret == 0 ) - return 4; // Just simple buffered molecule - if ( src[0].element()->cinfo()->isA( "StimulusTable" ) ) - return ret; // Following a table, this is fine. + static const Finfo* setNinitFinfo = + PoolBase::initCinfo()->findFinfo( "set_nInit" ); + static const Finfo* setConcInitFinfo = + PoolBase::initCinfo()->findFinfo( "set_concInit" ); + unsigned int ret = 0; + vector< Id > src; + if ( id.element()->cinfo()->isA( "BufPool" ) ) + { + if ( id.element()->getNeighbors( src, setConcInitFinfo ) > 0 ) + { + ret = 2; + } + else if ( id.element()->getNeighbors( src, setNinitFinfo ) > 0 ) + { + ret = 4; + } + } + else + { + return 0; + } + if ( ret == 0 ) + return 4; // Just simple buffered molecule + if ( src[0].element()->cinfo()->isA( "StimulusTable" ) ) + return ret; // Following a table, this is fine. - // Fallback: I have no idea what sent it the input, assume it is legit. - return ret; + // Fallback: I have no idea what sent it the input, assume it is legit. + return ret; } void writePool( ofstream& fout, Id id, - string colour, string textcolour, - double x, double y, Id comptid,int comptIndex ) + string colour, string textcolour, + double x, double y, Id comptid,int comptIndex ) { - string poolPar = Field <string> :: get(comptid,"name"); - string pooltype = Field < string > :: get(id,"className"); - double diffConst = Field< double >::get( id, "diffConst" ); - double concInit = Field< double >::get( id, "concInit" ); - //double conc = Field< double >::get( id, "conc" ); - double nInit = Field< double >::get( id, "nInit" ); - //double n = Field< double >::get( id, "n" ); - double volume = Field< double >::get( id, "volume" ); - string geometry; - stringstream geometryTemp ; - unsigned int slave_enable = 0; - if (pooltype == "BufPool" or pooltype == "ZombieBufPool") - { vector< Id > children = Field< vector< Id > >::get( id, "children" ); - if (children.size() == 0) - slave_enable = 4; - for ( vector< Id >::iterator i = children.begin(); i != children.end(); ++i ) - { string funcpath = Field <string> :: get(*i,"path"); - string clsname = Field <string> :: get(*i,"className"); - if (clsname == "Function" or clsname == "ZombieFunction") - slave_enable = 0; - else - slave_enable = 4; + string poolPar = Field <string> :: get(comptid,"name"); + string pooltype = Field < string > :: get(id,"className"); + double diffConst = Field< double >::get( id, "diffConst" ); + double concInit = Field< double >::get( id, "concInit" ); + //double conc = Field< double >::get( id, "conc" ); + double nInit = Field< double >::get( id, "nInit" ); + //double n = Field< double >::get( id, "n" ); + double volume = Field< double >::get( id, "volume" ); + string geometry; + stringstream geometryTemp ; + unsigned int slave_enable = 0; + if (pooltype == "BufPool" or pooltype == "ZombieBufPool") + { + vector< Id > children = Field< vector< Id > >::get( id, "children" ); + if (children.size() == 0) + slave_enable = 4; + for ( vector< Id >::iterator i = children.begin(); i != children.end(); ++i ) + { + string funcpath = Field <string> :: get(*i,"path"); + string clsname = Field <string> :: get(*i,"className"); + if (clsname == "Function" or clsname == "ZombieFunction") + slave_enable = 0; + else + slave_enable = 4; - } - } - if (comptIndex > 0) - geometryTemp << "/geometry[" << comptIndex <<"]"; - else - geometryTemp << "/geometry"; - - // simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable - - fout << "simundump kpool /kinetics" << trimPath(id,comptid) << " 0 " << - diffConst << " " << - 0 << " " << - 0 << " " << - 0 << " " << - nInit << " " << - 0 << " " << 0 << " " << // mwt, nMin - volume * NA * 1e-3 << " " << // volscale - slave_enable << //GENESIS FIELD HERE. - " /kinetics"<< geometryTemp.str() << " " << - colour << " " << textcolour << " " << x << " " << y << " 0\n"; + } + } + if (comptIndex > 0) + geometryTemp << "/geometry[" << comptIndex <<"]"; + else + geometryTemp << "/geometry"; + + // simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable + + fout << "simundump kpool /kinetics" << trimPath(id,comptid) << " 0 " << + diffConst << " " << + 0 << " " << + 0 << " " << + 0 << " " << + nInit << " " << + 0 << " " << 0 << " " << // mwt, nMin + volume * NA * 1e-3 << " " << // volscale + slave_enable << //GENESIS FIELD HERE. + " /kinetics"<< geometryTemp.str() << " " << + colour << " " << textcolour << " " << x << " " << y << " 0\n"; } void writePlot( ofstream& fout, Id id, - string colour, string textcolour, - double x, double y ) + string colour, string textcolour, + double x, double y ) { string path = id.path(); size_t pos = path.find( "/graphs" ); @@ -291,143 +304,148 @@ void writePlot( ofstream& fout, Id id, void writeGui( ofstream& fout ) { - fout << "simundump xgraph /graphs/conc1 0 0 99 0.001 0.999 0\n" - "simundump xgraph /graphs/conc2 0 0 100 0 1 0\n" - "simundump xgraph /moregraphs/conc3 0 0 100 0 1 0\n" - "simundump xgraph /moregraphs/conc4 0 0 100 0 1 0\n" - "simundump xcoredraw /edit/draw 0 -6 4 -2 6\n" - "simundump xtree /edit/draw/tree 0 \\\n" - " /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \"edit_elm.D <v>; drag_from_edit.w <d> <S> <x> <y> <z>\" auto 0.6\n" - "simundump xtext /file/notes 0 1\n"; + fout << "simundump xgraph /graphs/conc1 0 0 99 0.001 0.999 0\n" + "simundump xgraph /graphs/conc2 0 0 100 0 1 0\n" + "simundump xgraph /moregraphs/conc3 0 0 100 0 1 0\n" + "simundump xgraph /moregraphs/conc4 0 0 100 0 1 0\n" + "simundump xcoredraw /edit/draw 0 -6 4 -2 6\n" + "simundump xtree /edit/draw/tree 0 \\\n" + " /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \"edit_elm.D <v>; drag_from_edit.w <d> <S> <x> <y> <z>\" auto 0.6\n" + "simundump xtext /file/notes 0 1\n"; } void writeFooter( ofstream& fout ) { - fout << "\nenddump\n"; - fout << "complete_loading\n"; + fout << "\nenddump\n"; + fout << "complete_loading\n"; } void storeMMenzMsgs( Id enz, vector< string >& msgs, Id comptid ) { - Id enzparentId = Field <ObjId> :: get(enz,"parent"); - string enzPar = Field <string> :: get(enzparentId,"name"); - string enzName = Field<string> :: get(enz,"name"); - - vector < Id > srct = LookupField <string,vector < Id> >::get(enz, "neighbors","sub"); - for (vector <Id> :: iterator rsub = srct.begin();rsub != srct.end();rsub++) - { - string s = "addmsg /kinetics" + trimPath(*rsub, comptid) + " /kinetics" + trimPath(enz, comptid) + " SUBSTRATE n"; - msgs.push_back( s ); - s = "addmsg /kinetics" + trimPath(enz, comptid) + " /kinetics" + trimPath( *rsub, comptid ) + " REAC sA B"; - msgs.push_back( s ); - } - vector < Id > prct = LookupField <string,vector < Id> >::get(enz, "neighbors","prd"); - for (vector <Id> :: iterator rprd = prct.begin();rprd != prct.end();rprd++) - { - string s = "addmsg /kinetics" + trimPath( enz, comptid ) + " /kinetics" + trimPath(*rprd, comptid) + " MM_PRD pA"; - msgs.push_back( s ); - } - vector < Id > enzC = LookupField <string,vector < Id> >::get(enz, "neighbors","enzDest"); - for (vector <Id> :: iterator enzCl = enzC.begin();enzCl != enzC.end();enzCl++) - { - string s = "addmsg /kinetics" + trimPath( *enzCl, comptid ) + " /kinetics" + trimPath(enz, comptid) + " ENZYME n"; - msgs.push_back( s ); - } + Id enzparentId = Field <ObjId> :: get(enz,"parent"); + string enzPar = Field <string> :: get(enzparentId,"name"); + string enzName = Field<string> :: get(enz,"name"); + + vector < Id > srct = LookupField <string,vector < Id> >::get(enz, "neighbors","sub"); + for (vector <Id> :: iterator rsub = srct.begin(); rsub != srct.end(); rsub++) + { + string s = "addmsg /kinetics" + trimPath(*rsub, comptid) + " /kinetics" + trimPath(enz, comptid) + " SUBSTRATE n"; + msgs.push_back( s ); + s = "addmsg /kinetics" + trimPath(enz, comptid) + " /kinetics" + trimPath( *rsub, comptid ) + " REAC sA B"; + msgs.push_back( s ); + } + vector < Id > prct = LookupField <string,vector < Id> >::get(enz, "neighbors","prd"); + for (vector <Id> :: iterator rprd = prct.begin(); rprd != prct.end(); rprd++) + { + string s = "addmsg /kinetics" + trimPath( enz, comptid ) + " /kinetics" + trimPath(*rprd, comptid) + " MM_PRD pA"; + msgs.push_back( s ); + } + vector < Id > enzC = LookupField <string,vector < Id> >::get(enz, "neighbors","enzDest"); + for (vector <Id> :: iterator enzCl = enzC.begin(); enzCl != enzC.end(); enzCl++) + { + string s = "addmsg /kinetics" + trimPath( *enzCl, comptid ) + " /kinetics" + trimPath(enz, comptid) + " ENZYME n"; + msgs.push_back( s ); + } } void storeCplxEnzMsgs( Id enz, vector< string >& msgs, Id comptid ) -{ Id enzparentId = Field <ObjId> :: get(enz,"parent"); - string enzPar = Field <string> :: get(enzparentId,"name"); - string enzName = Field<string> :: get(enz,"name"); - - vector < Id > srct = LookupField <string,vector < Id> >::get(enz, "neighbors","sub"); - for (vector <Id> :: iterator rsub = srct.begin();rsub != srct.end();rsub++) - { - string s = "addmsg /kinetics" + trimPath(*rsub, comptid) + " /kinetics" + trimPath(enz, comptid) + " SUBSTRATE n"; - msgs.push_back( s ); - s = "addmsg /kinetics" + trimPath(enz, comptid) + " /kinetics" + trimPath( *rsub, comptid ) + " REAC sA B"; - msgs.push_back( s ); - } - vector < Id > prct = LookupField <string,vector < Id> >::get(enz, "neighbors","prd"); - for (vector <Id> :: iterator rprd = prct.begin();rprd != prct.end();rprd++) - { - string s = "addmsg /kinetics" + trimPath( enz, comptid ) + " /kinetics" + trimPath(*rprd, comptid) + " MM_PRD pA"; - msgs.push_back( s ); - } - vector < Id > enzC = LookupField <string,vector < Id> >::get(enz, "neighbors","enzOut"); - for (vector <Id> :: iterator enzCl = enzC.begin();enzCl != enzC.end();enzCl++) - { - string s = "addmsg /kinetics" + trimPath( *enzCl, comptid ) + " /kinetics" + trimPath(enz, comptid) + " ENZYME n"; - msgs.push_back( s ); - s = "addmsg /kinetics" + trimPath( enz, comptid ) + " /kinetics" + trimPath(*enzCl, comptid) + " REAC eA B"; - msgs.push_back( s ); - } +{ + Id enzparentId = Field <ObjId> :: get(enz,"parent"); + string enzPar = Field <string> :: get(enzparentId,"name"); + string enzName = Field<string> :: get(enz,"name"); + + vector < Id > srct = LookupField <string,vector < Id> >::get(enz, "neighbors","sub"); + for (vector <Id> :: iterator rsub = srct.begin(); rsub != srct.end(); rsub++) + { + string s = "addmsg /kinetics" + trimPath(*rsub, comptid) + " /kinetics" + trimPath(enz, comptid) + " SUBSTRATE n"; + msgs.push_back( s ); + s = "addmsg /kinetics" + trimPath(enz, comptid) + " /kinetics" + trimPath( *rsub, comptid ) + " REAC sA B"; + msgs.push_back( s ); + } + vector < Id > prct = LookupField <string,vector < Id> >::get(enz, "neighbors","prd"); + for (vector <Id> :: iterator rprd = prct.begin(); rprd != prct.end(); rprd++) + { + string s = "addmsg /kinetics" + trimPath( enz, comptid ) + " /kinetics" + trimPath(*rprd, comptid) + " MM_PRD pA"; + msgs.push_back( s ); + } + vector < Id > enzC = LookupField <string,vector < Id> >::get(enz, "neighbors","enzOut"); + for (vector <Id> :: iterator enzCl = enzC.begin(); enzCl != enzC.end(); enzCl++) + { + string s = "addmsg /kinetics" + trimPath( *enzCl, comptid ) + " /kinetics" + trimPath(enz, comptid) + " ENZYME n"; + msgs.push_back( s ); + s = "addmsg /kinetics" + trimPath( enz, comptid ) + " /kinetics" + trimPath(*enzCl, comptid) + " REAC eA B"; + msgs.push_back( s ); + } } void storeEnzMsgs( Id enz, vector< string >& msgs, Id comptid ) { - string enzClass = Field < string > :: get(enz,"className"); - if (enzClass == "ZombieMMenz" or enzClass == "MMenz") - storeMMenzMsgs(enz, msgs, comptid); - else - storeCplxEnzMsgs( enz, msgs, comptid ); + string enzClass = Field < string > :: get(enz,"className"); + if (enzClass == "ZombieMMenz" or enzClass == "MMenz") + storeMMenzMsgs(enz, msgs, comptid); + else + storeCplxEnzMsgs( enz, msgs, comptid ); } void storeReacMsgs( Id reac, vector< string >& msgs, Id comptid ) { - vector < Id > srct = LookupField <string,vector < Id> >::get(reac, "neighbors","sub"); - for (vector <Id> :: iterator rsub = srct.begin();rsub != srct.end();rsub++) - { string s = "addmsg /kinetics" + trimPath(*rsub, comptid) + " /kinetics" + trimPath(reac, comptid) + " SUBSTRATE n"; - msgs.push_back( s ); - s = "addmsg /kinetics" + trimPath(reac, comptid) + " /kinetics" + trimPath( *rsub, comptid ) + " REAC A B"; - msgs.push_back( s ); - } - vector < Id > prct = LookupField <string,vector < Id> >::get(reac, "neighbors","prd"); - for (vector <Id> :: iterator rprd = prct.begin();rprd != prct.end();rprd++) - { string rpath = Field <string> :: get(reac,"path"); - string cpath = Field <string> :: get(comptid,"path"); - string prdPath = Field <string> :: get(*rprd,"path"); - string s = "addmsg /kinetics" + trimPath( *rprd, comptid ) + " /kinetics" + trimPath(reac, comptid) + " PRODUCT n"; - msgs.push_back( s ); - s = "addmsg /kinetics" + trimPath(reac, comptid) + " /kinetics" + trimPath( *rprd,comptid ) + " REAC B A"; - msgs.push_back( s ); - } + vector < Id > srct = LookupField <string,vector < Id> >::get(reac, "neighbors","sub"); + for (vector <Id> :: iterator rsub = srct.begin(); rsub != srct.end(); rsub++) + { + string s = "addmsg /kinetics" + trimPath(*rsub, comptid) + " /kinetics" + trimPath(reac, comptid) + " SUBSTRATE n"; + msgs.push_back( s ); + s = "addmsg /kinetics" + trimPath(reac, comptid) + " /kinetics" + trimPath( *rsub, comptid ) + " REAC A B"; + msgs.push_back( s ); + } + vector < Id > prct = LookupField <string,vector < Id> >::get(reac, "neighbors","prd"); + for (vector <Id> :: iterator rprd = prct.begin(); rprd != prct.end(); rprd++) + { + string rpath = Field <string> :: get(reac,"path"); + string cpath = Field <string> :: get(comptid,"path"); + string prdPath = Field <string> :: get(*rprd,"path"); + string s = "addmsg /kinetics" + trimPath( *rprd, comptid ) + " /kinetics" + trimPath(reac, comptid) + " PRODUCT n"; + msgs.push_back( s ); + s = "addmsg /kinetics" + trimPath(reac, comptid) + " /kinetics" + trimPath( *rprd,comptid ) + " REAC B A"; + msgs.push_back( s ); + } } void storeFunctionMsgs( Id func, vector< string >& msgs,map < double, pair<Id, int> > & compt_vol ) { - // Get the msg sources into this Function object. - ObjId poolPath = Neutral::parent( func.eref() ); - double poolvol = Field < double > :: get(poolPath,"Volume"); - Id poolParentId = compt_vol[poolvol].first; - string poolParent = Field <string> :: get(compt_vol[poolvol].first,"name"); - Id xi(func.value()+1); - vector < Id > func_input = LookupField <string,vector < Id> >::get(xi, "neighbors","input"); - - for (vector <Id> :: iterator funcIp = func_input.begin();funcIp != func_input.end();funcIp++) - { string funcIp_path = Field < string > :: get(*funcIp,"path"); - double vol = Field < double > :: get(*funcIp,"Volume"); - Id parentId = compt_vol[vol].first; - string parentname = Field <string> :: get(parentId,"name"); - string s = "addmsg /kinetics" + trimPath(*funcIp, parentId)+ " /kinetics" + trimPath(poolPath,poolParentId) + - " SUMTOTAL n nInit"; - msgs.push_back(s); - } + // Get the msg sources into this Function object. + ObjId poolPath = Neutral::parent( func.eref() ); + double poolvol = Field < double > :: get(poolPath,"Volume"); + Id poolParentId = compt_vol[poolvol].first; + string poolParent = Field <string> :: get(compt_vol[poolvol].first,"name"); + Id xi(func.value()+1); + vector < Id > func_input = LookupField <string,vector < Id> >::get(xi, "neighbors","input"); + + for (vector <Id> :: iterator funcIp = func_input.begin(); funcIp != func_input.end(); funcIp++) + { + string funcIp_path = Field < string > :: get(*funcIp,"path"); + double vol = Field < double > :: get(*funcIp,"Volume"); + Id parentId = compt_vol[vol].first; + string parentname = Field <string> :: get(parentId,"name"); + string s = "addmsg /kinetics" + trimPath(*funcIp, parentId)+ " /kinetics" + trimPath(poolPath,poolParentId) + + " SUMTOTAL n nInit"; + msgs.push_back(s); + } } void storePlotMsgs( Id tab, vector< string >& msgs, Id pool, string bg, Id comptid) -{ string tabPath = tab.path(); - string poolPath = Field <string> :: get(pool,"path"); - string poolName = Field <string> :: get(pool,"name"); - - size_t pos = tabPath.find( "/graphs" ); - if ( pos == string::npos ) - pos = tabPath.find( "/moregraphs" ); - assert( pos != string::npos ); - tabPath = tabPath.substr( pos ); - string s = "addmsg /kinetics" + trimPath( poolPath, comptid) + " " + tabPath + - " PLOT Co *" + poolName + " *" + bg; - msgs.push_back( s ); +{ + string tabPath = tab.path(); + string poolPath = Field <string> :: get(pool,"path"); + string poolName = Field <string> :: get(pool,"name"); + + size_t pos = tabPath.find( "/graphs" ); + if ( pos == string::npos ) + pos = tabPath.find( "/moregraphs" ); + assert( pos != string::npos ); + tabPath = tabPath.substr( pos ); + string s = "addmsg /kinetics" + trimPath( poolPath, comptid) + " " + tabPath + + " PLOT Co *" + poolName + " *" + bg; + msgs.push_back( s ); } /** @@ -436,52 +454,54 @@ void storePlotMsgs( Id tab, vector< string >& msgs, Id pool, string bg, Id compt */ double estimateSimTimes( double& simDt, double& plotDt ) { - double runTime = Field< double >::get( Id( 1 ), "runTime" ); - if ( runTime <= 0 ) - runTime = 100.0; - vector< double > dts = - Field< vector< double> >::get( Id( 1 ), "dts" ); - - simDt = dts[11]; - plotDt = dts[18]; - cout << "estimatesimtimes" << simDt << plotDt; - if ( plotDt <= 0 ) - plotDt = runTime / 200.0; - if ( simDt == 0 ) - simDt = 0.01; - if ( simDt > plotDt ) - simDt = plotDt / 100; - - return runTime; + double runTime = Field< double >::get( Id( 1 ), "runTime" ); + if ( runTime <= 0 ) + runTime = 100.0; + vector< double > dts = + Field< vector< double> >::get( Id( 1 ), "dts" ); + + simDt = dts[11]; + plotDt = dts[18]; + cout << "estimatesimtimes" << simDt << plotDt; + if ( plotDt <= 0 ) + plotDt = runTime / 200.0; + if ( simDt == 0 ) + simDt = 0.01; + if ( simDt > plotDt ) + simDt = plotDt / 100; + + return runTime; } /// Returns an estimate of the default volume used in the model. double estimateDefaultVol( Id model ) { - vector< Id > children = - Field< vector< Id > >::get( model, "children" ); - vector< double > vols; - double maxVol = 0; - for ( vector< Id >::iterator i = children.begin(); - i != children.end(); ++i ) { - if ( i->element()->cinfo()->isA( "ChemCompt" ) ) { - double v = Field< double >::get( *i, "volume" ); - if ( i->element()->getName() == "kinetics" ) - return v; - vols.push_back( v ); - if ( maxVol < v ) - maxVol = v; - } - } - if ( maxVol > 0 ) - return maxVol; - return 1.0e-15; + vector< Id > children = + Field< vector< Id > >::get( model, "children" ); + vector< double > vols; + double maxVol = 0; + for ( vector< Id >::iterator i = children.begin(); + i != children.end(); ++i ) + { + if ( i->element()->cinfo()->isA( "ChemCompt" ) ) + { + double v = Field< double >::get( *i, "volume" ); + if ( i->element()->getName() == "kinetics" ) + return v; + vols.push_back( v ); + if ( maxVol < v ) + maxVol = v; + } + } + if ( maxVol > 0 ) + return maxVol; + return 1.0e-15; } void writeMsgs( ofstream& fout, const vector< string >& msgs ) { - for ( vector< string >::const_iterator i = msgs.begin(); - i != msgs.end(); ++i ) - fout << *i << endl; + for ( vector< string >::const_iterator i = msgs.begin(); + i != msgs.end(); ++i ) + fout << *i << endl; } void writeGroup(ofstream& fout,Id model) { @@ -489,7 +509,7 @@ void writeGroup(ofstream& fout,Id model) int x = 10; int y = 20; int num = wildcardFind( model.path() + "/##[TYPE=Neutral]", group ); - for ( vector< ObjId >::iterator itr = group.begin(); itr != group.end();itr++) + for ( vector< ObjId >::iterator itr = group.begin(); itr != group.end(); itr++) { string path = Field<string>::get(*itr,"path"); size_t pos = path.find( "/kinetics" ); @@ -497,149 +517,158 @@ void writeGroup(ofstream& fout,Id model) { path = path.substr( pos ); fout << "simundump group " << path << " 0 " << - "blue" << " " << "green" << " x 0 0 \"\" defaultfile \\\n"; + "blue" << " " << "green" << " x 0 0 \"\" defaultfile \\\n"; fout << " defaultfile.g 0 0 0 " << x << " " << y << " 0\n"; } } } void writeKkit( Id model, const string& fname ) -{ ofstream fout( fname.c_str(), ios::out ); - vector< ObjId > chemCompt; - vector< string > msgs; - double simDt; - double plotDt; - - double runTime = estimateSimTimes( simDt, plotDt ); - double defaultVol = estimateDefaultVol( model ); - writeHeader( fout, simDt, plotDt, runTime, defaultVol ); - string bg = "cyan"; - string fg = "black"; - double x = 0; - double y = 0; - - map < double, pair<Id, int> > compt_vol; - - unsigned int num = wildcardFind( model.path() + "/##[ISA=ChemCompt]", chemCompt ); - if ( num == 0 ) { - cout << "Warning: writeKkit:: No model found on " << model << - endl; - return; - } - for ( vector< ObjId >::iterator itr = chemCompt.begin(); itr != chemCompt.end();itr++) - { - vector < unsigned int>dims; - unsigned int dims_size; - dims_size = 1; - unsigned index = 0; - string comptPath = Field<string>::get(*itr,"path"); - string comptname = Field<string>::get(*itr,"name"); - if (comptname != "kinetics") - { - fout << "simundump group /kinetics/" << comptname << " 0 " << - "blue" << " " << "green" << " x 0 0 \"\" defaultfile \\\n"; - fout << " defaultfile.g 0 0 0 " << rand() % 10 + 1 << " " << rand() % 10 + 1 << " 0\n"; - } - double size = Field<double>::get(ObjId(*itr,index),"Volume"); - unsigned int ndim = Field<unsigned int>::get(ObjId(*itr,index),"NumDimensions"); - ostringstream geometry; - int vecIndex = itr-chemCompt.begin(); - if (vecIndex > 0) - geometry << "simundump geometry /kinetics" << "/geometry[" << vecIndex <<"] 0 " << size << " " << ndim << " sphere " <<" \"\" white black 0 0 0\n"; - else - geometry << "simundump geometry /kinetics" << "/geometry 0 " << size << " " << ndim << " sphere " <<" \"\" white black 0 0 0\n"; - fout << geometry.str(); - compt_vol.insert(make_pair(size,make_pair(*itr,vecIndex))); - } // compartmentclose - writeGroup(fout, model); - map<double, pair<Id, int> >::iterator compt; - for (compt = compt_vol.begin(); compt != compt_vol.end(); compt++) - { - string comptPath = Field<string>::get(compt->second.first,"path"); - // Species - vector< ObjId > Compt_spe; - wildcardFind(comptPath+"/##[ISA=PoolBase]",Compt_spe); - int species_size = 1; - string objname; - for (vector <ObjId> :: iterator itrp = Compt_spe.begin();itrp != Compt_spe.end();itrp++) - { string path = Field <string> :: get (*itrp,"path"); - Id enzPoolparent = Field <ObjId> :: get(*itrp,"parent"); - string enzpoolClass = Field <string> :: get(enzPoolparent,"className"); - if (enzpoolClass != "ZombieEnz" or enzpoolClass != "Enz") - { Id annotaId( path+"/info"); - if ( annotaId != Id() ) - { double x = Field <double> :: get(annotaId,"x"); - double y = Field <double> :: get(annotaId,"y"); - string fg = Field <string> :: get(annotaId,"textColor"); - string bg = Field <string> :: get(annotaId,"color"); - writePool(fout, *itrp,bg,fg,x,y,compt->second.first,compt->second.second); - } - } - } //species is closed - vector< ObjId > Compt_Func; - wildcardFind(comptPath+"/##[ISA=Function]",Compt_Func); - for (vector <ObjId> :: iterator itrF= Compt_Func.begin();itrF != Compt_Func.end();itrF++) - { storeFunctionMsgs( *itrF, msgs,compt_vol); - } - // Reaction - vector< ObjId > Compt_Reac; - wildcardFind(comptPath+"/##[ISA=ReacBase]",Compt_Reac); - for (vector <ObjId> :: iterator itrR= Compt_Reac.begin();itrR != Compt_Reac.end();itrR++) - { - string path = Field<string> :: get(*itrR,"path"); - Id annotaId( path+"/info"); - string noteClass = Field<string> :: get(annotaId,"className"); - string notes; - double x = Field <double> :: get(annotaId,"x"); - double y = Field <double> :: get(annotaId,"y"); - string fg = Field <string> :: get(annotaId,"textColor"); - string bg = Field <string> :: get(annotaId,"color"); - writeReac( fout, *itrR, bg, fg, x, y, compt->second.first); - storeReacMsgs( *itrR, msgs, compt->second.first ); - }// reaction - vector< ObjId > Compt_Enz; - wildcardFind(comptPath+"/##[ISA=EnzBase]",Compt_Enz); - for (vector <ObjId> :: iterator itrE= Compt_Enz.begin();itrE != Compt_Enz.end();itrE++) - { string path = Field<string> :: get(*itrE,"path"); - Id annotaId( path+"/info"); - string noteClass = Field<string> :: get(annotaId,"className"); - string notes; - double x = Field <double> :: get(annotaId,"x"); - double y = Field <double> :: get(annotaId,"y"); - string fg = Field <string> :: get(annotaId,"textColor"); - string bg = Field <string> :: get(annotaId,"color"); - writeEnz( fout, *itrE, bg, fg, x, y, compt->second.first); - storeEnzMsgs( *itrE, msgs, compt->second.first); - }// reaction - - } //compatment loop - writeGui ( fout); - - /* Table */ - - vector< ObjId > table; - wildcardFind(model.path()+"/##[ISA=Table2]",table); - for (vector <ObjId> :: iterator itrT= table.begin();itrT != table.end();itrT++) - { string tabPath = Field <string> :: get(*itrT,"path"); - vector < Id > tabSrc = LookupField <string,vector < Id> >::get(*itrT, "neighbors","requestOut"); - for (vector <Id> :: iterator tabItem= tabSrc.begin();tabItem != tabSrc.end();tabItem++) - { string path = Field <string> :: get(*tabItem,"path"); - double vol = Field < double> :: get (*tabItem,"Volume"); - //Trying to find the compartment name via volume - //otherwise if we go via parent, sometimes it might - // get groupname so maped compartment Id and volume - - Id parentId = compt_vol[vol].first; - string parentname = Field <string> :: get(parentId,"name"); - Id annotaId(path+"/info"); - double x = Field <double> :: get(annotaId,"x"); - double y = Field <double> :: get(annotaId,"y"); - string bg = Field <string> :: get(annotaId,"textColor"); - string fg = Field <string> :: get(annotaId,"color"); - writePlot( fout, *itrT, bg, fg, x, y ); - storePlotMsgs( *itrT, msgs,*tabItem,fg, parentId); +{ + ofstream fout( fname.c_str(), ios::out ); + vector< ObjId > chemCompt; + vector< string > msgs; + double simDt; + double plotDt; + + double runTime = estimateSimTimes( simDt, plotDt ); + double defaultVol = estimateDefaultVol( model ); + writeHeader( fout, simDt, plotDt, runTime, defaultVol ); + string bg = "cyan"; + string fg = "black"; + double x = 0; + double y = 0; + + map < double, pair<Id, int> > compt_vol; + + unsigned int num = wildcardFind( model.path() + "/##[ISA=ChemCompt]", chemCompt ); + if ( num == 0 ) + { + cout << "Warning: writeKkit:: No model found on " << model << + endl; + return; + } + for ( vector< ObjId >::iterator itr = chemCompt.begin(); itr != chemCompt.end(); itr++) + { + vector < unsigned int>dims; + unsigned int dims_size; + dims_size = 1; + unsigned index = 0; + string comptPath = Field<string>::get(*itr,"path"); + string comptname = Field<string>::get(*itr,"name"); + if (comptname != "kinetics") + { + fout << "simundump group /kinetics/" << comptname << " 0 " << + "blue" << " " << "green" << " x 0 0 \"\" defaultfile \\\n"; + fout << " defaultfile.g 0 0 0 " << rand() % 10 + 1 << " " << rand() % 10 + 1 << " 0\n"; + } + double size = Field<double>::get(ObjId(*itr,index),"Volume"); + unsigned int ndim = Field<unsigned int>::get(ObjId(*itr,index),"NumDimensions"); + ostringstream geometry; + int vecIndex = itr-chemCompt.begin(); + if (vecIndex > 0) + geometry << "simundump geometry /kinetics" << "/geometry[" << vecIndex <<"] 0 " << size << " " << ndim << " sphere " <<" \"\" white black 0 0 0\n"; + else + geometry << "simundump geometry /kinetics" << "/geometry 0 " << size << " " << ndim << " sphere " <<" \"\" white black 0 0 0\n"; + fout << geometry.str(); + compt_vol.insert(make_pair(size,make_pair(*itr,vecIndex))); + } // compartmentclose + writeGroup(fout, model); + map<double, pair<Id, int> >::iterator compt; + for (compt = compt_vol.begin(); compt != compt_vol.end(); compt++) + { + string comptPath = Field<string>::get(compt->second.first,"path"); + // Species + vector< ObjId > Compt_spe; + wildcardFind(comptPath+"/##[ISA=PoolBase]",Compt_spe); + int species_size = 1; + string objname; + for (vector <ObjId> :: iterator itrp = Compt_spe.begin(); itrp != Compt_spe.end(); itrp++) + { + string path = Field <string> :: get (*itrp,"path"); + Id enzPoolparent = Field <ObjId> :: get(*itrp,"parent"); + string enzpoolClass = Field <string> :: get(enzPoolparent,"className"); + if (enzpoolClass != "ZombieEnz" or enzpoolClass != "Enz") + { + Id annotaId( path+"/info"); + if ( annotaId != Id() ) + { + double x = Field <double> :: get(annotaId,"x"); + double y = Field <double> :: get(annotaId,"y"); + string fg = Field <string> :: get(annotaId,"textColor"); + string bg = Field <string> :: get(annotaId,"color"); + writePool(fout, *itrp,bg,fg,x,y,compt->second.first,compt->second.second); + } + } + } //species is closed + vector< ObjId > Compt_Func; + wildcardFind(comptPath+"/##[ISA=Function]",Compt_Func); + for (vector <ObjId> :: iterator itrF= Compt_Func.begin(); itrF != Compt_Func.end(); itrF++) + { + storeFunctionMsgs( *itrF, msgs,compt_vol); + } + // Reaction + vector< ObjId > Compt_Reac; + wildcardFind(comptPath+"/##[ISA=ReacBase]",Compt_Reac); + for (vector <ObjId> :: iterator itrR= Compt_Reac.begin(); itrR != Compt_Reac.end(); itrR++) + { + string path = Field<string> :: get(*itrR,"path"); + Id annotaId( path+"/info"); + string noteClass = Field<string> :: get(annotaId,"className"); + string notes; + double x = Field <double> :: get(annotaId,"x"); + double y = Field <double> :: get(annotaId,"y"); + string fg = Field <string> :: get(annotaId,"textColor"); + string bg = Field <string> :: get(annotaId,"color"); + writeReac( fout, *itrR, bg, fg, x, y, compt->second.first); + storeReacMsgs( *itrR, msgs, compt->second.first ); + }// reaction + vector< ObjId > Compt_Enz; + wildcardFind(comptPath+"/##[ISA=EnzBase]",Compt_Enz); + for (vector <ObjId> :: iterator itrE= Compt_Enz.begin(); itrE != Compt_Enz.end(); itrE++) + { + string path = Field<string> :: get(*itrE,"path"); + Id annotaId( path+"/info"); + string noteClass = Field<string> :: get(annotaId,"className"); + string notes; + double x = Field <double> :: get(annotaId,"x"); + double y = Field <double> :: get(annotaId,"y"); + string fg = Field <string> :: get(annotaId,"textColor"); + string bg = Field <string> :: get(annotaId,"color"); + writeEnz( fout, *itrE, bg, fg, x, y, compt->second.first); + storeEnzMsgs( *itrE, msgs, compt->second.first); + }// reaction + + } //compatment loop + writeGui ( fout); + + /* Table */ + + vector< ObjId > table; + wildcardFind(model.path()+"/##[ISA=Table2]",table); + for (vector <ObjId> :: iterator itrT= table.begin(); itrT != table.end(); itrT++) + { + string tabPath = Field <string> :: get(*itrT,"path"); + vector < Id > tabSrc = LookupField <string,vector < Id> >::get(*itrT, "neighbors","requestOut"); + for (vector <Id> :: iterator tabItem= tabSrc.begin(); tabItem != tabSrc.end(); tabItem++) + { + string path = Field <string> :: get(*tabItem,"path"); + double vol = Field < double> :: get (*tabItem,"Volume"); + //Trying to find the compartment name via volume + //otherwise if we go via parent, sometimes it might + // get groupname so maped compartment Id and volume + + Id parentId = compt_vol[vol].first; + string parentname = Field <string> :: get(parentId,"name"); + Id annotaId(path+"/info"); + double x = Field <double> :: get(annotaId,"x"); + double y = Field <double> :: get(annotaId,"y"); + string bg = Field <string> :: get(annotaId,"textColor"); + string fg = Field <string> :: get(annotaId,"color"); + writePlot( fout, *itrT, bg, fg, x, y ); + storePlotMsgs( *itrT, msgs,*tabItem,fg, parentId); - } - }// table - writeMsgs( fout, msgs ); - writeFooter( fout ); + } + }// table + writeMsgs( fout, msgs ); + writeFooter( fout ); } diff --git a/moose-core/ksolve/BoostSys.cpp b/moose-core/ksolve/BoostSys.cpp index 4a3faf018f7acc4995b052d40bd6687a4c638a75..0a6e4eb33bb02ee10955f680d43070d7f4ae20cc 100644 --- a/moose-core/ksolve/BoostSys.cpp +++ b/moose-core/ksolve/BoostSys.cpp @@ -18,7 +18,7 @@ #include <iostream> #include "VoxelPools.h" -#ifdef USE_BOOST +#ifdef USE_BOOST_ODE BoostSys::BoostSys( ) : vp( NULL ) { ; } @@ -34,5 +34,6 @@ void BoostSys::operator()( const vector_type_ y VoxelPools::evalRates( y, dydt, t, vp ); } -#else /* ----- not USE_BOOST ----- */ -#endif /* ----- not USE_BOOST ----- */ +#else /* ----- not USE_BOOST_ODE ----- */ + +#endif /* ----- not USE_BOOST_ODE ----- */ diff --git a/moose-core/ksolve/BoostSys.h b/moose-core/ksolve/BoostSys.h index 8714b3d4541cdbf5a80cfb74d3fb734aa839afc3..ae97723a52ddf24e6cc10ac97f0da573b93ffceb 100644 --- a/moose-core/ksolve/BoostSys.h +++ b/moose-core/ksolve/BoostSys.h @@ -1,11 +1,10 @@ #ifndef BOOSTSYSTEM_H #define BOOSTSYSTEM_H -#ifdef USE_BOOST +#ifdef USE_BOOST_ODE #include <vector> #include <string> - #include <boost/numeric/odeint.hpp> typedef double value_type_; @@ -34,23 +33,23 @@ class VoxelPools; */ class BoostSys { - public: - BoostSys( ); - ~BoostSys(); +public: + BoostSys( ); + ~BoostSys( ); - /* Operator is called by boost ode-solver */ - void operator()( const vector_type_ y , vector_type_& dydt, const double t ); + /* Operator is called by boost ode-solver */ + void operator()( const vector_type_ y , vector_type_& dydt, const double t ); - /* Pointer to the arbitrary parameters of the system */ - VoxelPools* vp; - void* params; + /* Pointer to the arbitrary parameters of the system */ + VoxelPools* vp; + void* params; - double epsAbs; - double epsRel; - std::string method; + double epsAbs; + double epsRel; + std::string method; }; -#endif // USE_BOOST +#endif // USE_BOOST_ODE #endif /* end of include guard: BOOSTSYSTEM_H */ diff --git a/moose-core/ksolve/CMakeLists.txt b/moose-core/ksolve/CMakeLists.txt index c26bbcecedbd48da80fbb8f88831c1f2fd8dbdf8..f35588de2c69225086b36e306e023d546c88ae68 100644 --- a/moose-core/ksolve/CMakeLists.txt +++ b/moose-core/ksolve/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8) include(CheckIncludeFileCXX) include_directories(../builtins ../basecode ../utility ../kinetics) include_directories(../ ) include_directories(../mesh) include_directories(../external/muparser/include ) -IF(WITH_BOOST) +IF(WITH_BOOST_ODE) check_include_file_cxx( ${Boost_INCLUDE_DIRS}/boost/numeric/odeint.hpp ODEINT_EXISTS) # If boost distribution does not have its own odeint library, use the @@ -16,7 +16,7 @@ IF(WITH_BOOST) include_directories( ../external/boost-numeric-bindings ) elseif(WITH_GSL) include_directories( ${GSL_INCLUDE_DIRS} ) -endif(WITH_BOOST) +endif(WITH_BOOST_ODE) if(PARALLELIZED_SOLVERS) message( STATUS "Parallel version of KSolve and Gsolve" ) @@ -46,7 +46,7 @@ set(KSOLVE_SRCS if(WITH_GSL) list(APPEND KSOLVE_SRCS SteadyStateGsl.cpp ) -elseif(WITH_BOOST) +elseif(WITH_BOOST_ODE) list(APPEND KSOLVE_SRCS SteadyStateBoost.cpp ) list(APPEND KSOLVE_SRCS BoostSys.cpp) endif(WITH_GSL) diff --git a/moose-core/ksolve/Gsolve.cpp b/moose-core/ksolve/Gsolve.cpp index 25a5c060e7fcc6cb14c6be0550a1121b5842d548..c7f5cb8ac00bcc159ee2fc54c3260c0c2dd61630 100644 --- a/moose-core/ksolve/Gsolve.cpp +++ b/moose-core/ksolve/Gsolve.cpp @@ -6,10 +6,12 @@ ** GNU Lesser General Public License version 2.1 ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" +#include "../basecode/header.h" +#include "../basecode/global.h" -#include "VoxelPoolsBase.h" #include "../mesh/VoxelJunction.h" + +#include "VoxelPoolsBase.h" #include "XferInfo.h" #include "ZombiePoolInterface.h" @@ -21,7 +23,6 @@ #include "GssaSystem.h" #include "Stoich.h" #include "GssaVoxelPools.h" -#include "../randnum/randnum.h" #include <future> #include <atomic> @@ -215,6 +216,11 @@ Gsolve::Gsolve() : ; } +Gsolve& Gsolve::operator=(const Gsolve& ) +{ + return *this; +} + Gsolve::~Gsolve() { ; @@ -419,7 +425,9 @@ void Gsolve::process( const Eref& e, ProcPtr p ) *i = round( *i ); #else double base = floor( *i ); - if ( mtrand() >= (*i - base) ) + + // Use global RNG. + if ( moose::mtrand() >= (*i - base) ) *i = base; else *i = base + 1.0; diff --git a/moose-core/ksolve/Gsolve.h b/moose-core/ksolve/Gsolve.h index 78f572abc3a32d03af85a67812f67bb34ee04398..cb51181468c1a30966a0f53593538eb1658bca82 100644 --- a/moose-core/ksolve/Gsolve.h +++ b/moose-core/ksolve/Gsolve.h @@ -17,6 +17,9 @@ public: Gsolve(); ~Gsolve(); + // Assignment operator required for c++11 + Gsolve& operator=(const Gsolve& ); + ////////////////////////////////////////////////////////////////// // Field assignment stuff ////////////////////////////////////////////////////////////////// diff --git a/moose-core/ksolve/GssaSystem.h b/moose-core/ksolve/GssaSystem.h index 6c81c5139f1efd24c1271957e099dacd5b16e7d0..c1b8ad91df09b453162f77215f31cdd38f255436 100644 --- a/moose-core/ksolve/GssaSystem.h +++ b/moose-core/ksolve/GssaSystem.h @@ -18,35 +18,40 @@ class Stoich; class GssaSystem { - public: - GssaSystem() - : stoich( 0 ), useRandInit( true ), isReady( false ) - {;} - vector< vector< unsigned int > > dependency; - vector< vector< unsigned int > > dependentMathExpn; - vector< vector< unsigned int > > ratesDependentOnPool; - - /// Transpose of stoichiometry matrix. - KinSparseMatrix transposeN; - Stoich* stoich; - - /** - * Flag: True when using probabilistic (random) rounding. - * When initializing the mol# from floating-point Sinit values, - * we have two options. One is to look at each Sinit, and round - * to the nearest integer. The other is to look at each Sinit, - * and probabilistically round up or down depending on the - * value. For example, if we had a Sinit value of 1.49, - * this would always be rounded to 1.0 if the flag is false, - * and would be rounded to 1.0 and 2.0 in the ratio 51:49 if - * the flag is true. - */ - bool useRandInit; - - /** - * Flag: True when all initialization is done. - */ - bool isReady; +public: + GssaSystem() + : stoich(0), useRandInit(true), isReady(false), honorMassConservation(true) + {;} + vector< vector< unsigned int > > dependency; + vector< vector< unsigned int > > dependentMathExpn; + vector< vector< unsigned int > > ratesDependentOnPool; + + /// Transpose of stoichiometry matrix. + KinSparseMatrix transposeN; + Stoich* stoich; + + /** + * Flag: True when using probabilistic (random) rounding. + * When initializing the mol# from floating-point Sinit values, + * we have two options. One is to look at each Sinit, and round + * to the nearest integer. The other is to look at each Sinit, + * and probabilistically round up or down depending on the + * value. For example, if we had a Sinit value of 1.49, + * this would always be rounded to 1.0 if the flag is false, + * and would be rounded to 1.0 and 2.0 in the ratio 51:49 if + * the flag is true. + */ + bool useRandInit = true; + + /** + * Flag: True when all initialization is done. + */ + bool isReady = false; + + /* When set to true, it makes sure that after rounding number of molecules, + * the sum of molecules is does not differ more than 1.0 molecules. + */ + bool honorMassConservation = true; }; #endif // _GSSA_SYSTEM_H diff --git a/moose-core/ksolve/GssaVoxelPools.cpp b/moose-core/ksolve/GssaVoxelPools.cpp index 273964301a5e40d0a8b853fdee1b198ccd3c616f..4128d0a6dcd65010cbe263fdcb178f83cdee3ef3 100644 --- a/moose-core/ksolve/GssaVoxelPools.cpp +++ b/moose-core/ksolve/GssaVoxelPools.cpp @@ -48,7 +48,7 @@ const double SAFETY_FACTOR = 1.0 + 1.0e-9; ////////////////////////////////////////////////////////////// GssaVoxelPools::GssaVoxelPools() : - VoxelPoolsBase(), t_( 0.0 ), atot_( 0.0 ) + VoxelPoolsBase(), t_( 0.0 ), atot_( 0.0 ) { ; } GssaVoxelPools::~GssaVoxelPools() @@ -78,15 +78,15 @@ void GssaVoxelPools::updateDependentMathExpn( g->stoich->funcs( *i )->evalPool( varS(), time ); } */ - /* + /* unsigned int numFuncs = g->stoich->getNumFuncs(); for( unsigned int i = 0; i < numFuncs; ++i ) { g->stoich->funcs( i )->evalPool( varS(), time ); } - */ - // This function is equivalent to the loop above. - g->stoich->updateFuncs( varS(), time ); + */ + // This function is equivalent to the loop above. + g->stoich->updateFuncs( varS(), time ); } void GssaVoxelPools::updateDependentRates( @@ -139,7 +139,7 @@ void GssaVoxelPools::setNumReac( unsigned int n ) */ bool GssaVoxelPools::refreshAtot( const GssaSystem* g ) { - g->stoich->updateFuncs( varS(), t_ ); + g->stoich->updateFuncs( varS(), t_ ); updateReacVelocities( g, S(), v_ ); atot_ = 0; for ( vector< double >::const_iterator @@ -178,8 +178,8 @@ void GssaVoxelPools::advance( const ProcInfo* p, const GssaSystem* g ) if ( atot_ <= 0.0 ) // reac system is stuck, will not advance. { t_ = nextt; - g->stoich->updateFuncs( varS(), t_ ); - // updateDependentMathExpn( g, 0, t_ ); + g->stoich->updateFuncs( varS(), t_ ); + // updateDependentMathExpn( g, 0, t_ ); return; } unsigned int rindex = pickReac(); @@ -191,8 +191,8 @@ void GssaVoxelPools::advance( const ProcInfo* p, const GssaSystem* g ) if ( !refreshAtot( g ) ) // Stuck state. { t_ = nextt; - g->stoich->updateFuncs( varS(), t_ ); - // updateDependentMathExpn( g, 0, t_ ); + g->stoich->updateFuncs( varS(), t_ ); + // updateDependentMathExpn( g, 0, t_ ); return; } // We had a roundoff error, fixed it, but now need to be sure @@ -208,17 +208,22 @@ void GssaVoxelPools::advance( const ProcInfo* p, const GssaSystem* g ) assert( rindex < v_.size() ); } +#if ENABLE_CPP11 + double sign = std::copysign( 1, v_[rindex] ); +#else double sign = double(v_[rindex] >= 0) - double(0 > v_[rindex] ); +#endif + g->transposeN.fireReac( rindex, Svec(), sign ); - numFire_[rindex]++; + numFire_[rindex]++; double r = rng_.uniform(); + while ( r <= 0.0 ) - { r = rng_.uniform(); - } + t_ -= ( 1.0 / atot_ ) * log( r ); - g->stoich->updateFuncs( varS(), t_ ); + g->stoich->updateFuncs( varS(), t_ ); // updateDependentMathExpn( g, rindex, t_ ); updateDependentRates( g->dependency[ rindex ], g->stoich ); } @@ -233,36 +238,66 @@ void GssaVoxelPools::reinit( const GssaSystem* g ) double* n = varS(); - if ( g->useRandInit ) + if( g->useRandInit ) { - // round up or down probabilistically depending on fractional - // num molecules. + vector<double> error(numVarPools, 0.0); + map<double, vector<Eref>> groupByVal; + for ( unsigned int i = 0; i < numVarPools; ++i ) { - double base = floor( n[i] ); + error[i] = n[i]; + double base = std::floor( n[i] ); assert( base >= 0.0 ); double frac = n[i] - base; - if ( rng_.uniform() > frac ) + if ( rng_.uniform() >= frac ) n[i] = base; else n[i] = base + 1.0; + + error[i] -= n[i]; + + //if( true ) + //{ + // //NOTE: Thats how I get the name of the pool at this index. + // Eref e = g->stoich->getPoolByIndex( i ).eref(); + // groupByVal[n[i]].push_back( e ); + + // // Guess the fix the error. + //} + + + } + + double extra = std::accumulate( error.begin(), error.end(), 0.0 ); + if( std::abs(extra) > 0.1 ) + { + cout << "WARNING: Extra " << extra + << " molecules in system after converting fractional to integer e.g. 1.1 = 1 (~90% of times) or 2 (~10% of times)." << endl; } } else // Just round to the nearest int. { for ( unsigned int i = 0; i < numVarPools; ++i ) { +#if ENABLE_CPP11 + // Just like rint but does not raise exception. + // See http://en.cppreference.com/w/cpp/numeric/math/nearbyint for + // details. + n[i] = std::nearbyint(n[i]); +#else n[i] = round( n[i] ); +#endif } } + t_ = 0.0; refreshAtot( g ); - numFire_.assign( v_.size(), 0 ); + numFire_.assign( v_.size(), 0 ); } vector< unsigned int > GssaVoxelPools::numFire() const { - return numFire_; + return numFire_; } ///////////////////////////////////////////////////////////////////////// diff --git a/moose-core/ksolve/GssaVoxelPools.h b/moose-core/ksolve/GssaVoxelPools.h index 716698a48037aab51363745fc19348b9536f415b..b0bc90e5c20487ae5e2ddfb7da0fa6893c6b520f 100644 --- a/moose-core/ksolve/GssaVoxelPools.h +++ b/moose-core/ksolve/GssaVoxelPools.h @@ -34,7 +34,7 @@ public: void advance( const ProcInfo* p, const GssaSystem* g ); - vector< unsigned int > numFire() const; + vector< unsigned int > numFire() const; /** * Cleans out all reac rates and recalculates atot. Needed whenever a @@ -88,8 +88,8 @@ private: vector< double > v_; // Possibly we should put independent RNGS, so save one here. - // Count how many times each reaction has fired. - vector< unsigned int > numFire_; + // Count how many times each reaction has fired. + vector< unsigned int > numFire_; /** * @brief RNG. diff --git a/moose-core/ksolve/Ksolve.cpp b/moose-core/ksolve/Ksolve.cpp index 8b7b5ac9ddeaa261724ad8eda3954cfc496d2010..b55d0d1212d43744be7a3232f7a8cb53cdcac03f 100644 --- a/moose-core/ksolve/Ksolve.cpp +++ b/moose-core/ksolve/Ksolve.cpp @@ -6,7 +6,7 @@ ** GNU Lesser General Public License version 2.1 ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" +#include "../basecode/header.h" #ifdef USE_GSL #include <gsl/gsl_errno.h> #include <gsl/gsl_matrix.h> @@ -21,7 +21,7 @@ #include "RateTerm.h" #include "FuncTerm.h" -#include "SparseMatrix.h" +#include "../basecode/SparseMatrix.h" #include "KinSparseMatrix.h" #include "Stoich.h" #include "../shell/Shell.h" @@ -217,7 +217,7 @@ Ksolve::Ksolve() : #if USE_GSL method_( "rk5" ), -#elif USE_BOOST +#elif USE_BOOST_ODE method_( "rk5a" ), #endif epsAbs_( 1e-7 ), @@ -265,7 +265,7 @@ void Ksolve::setMethod( string method ) "' not known, using rk5\n"; method_ = "rk5"; } -#elif USE_BOOST +#elif USE_BOOST_ODE // TODO: Check for boost related methods. method_ = method; #endif @@ -380,7 +380,7 @@ void Ksolve::setStoich( Id stoich ) pools_[i].setStoich( stoichPtr_, &ode ); // pools_[i].setIntDt( ode.initStepSize ); // We're setting it up anyway } -#elif USE_BOOST +#elif USE_BOOST_ODE ode.dimension = stoichPtr_->getNumAllPools(); ode.boostSys.epsAbs = epsAbs_; ode.boostSys.epsRel = epsRel_; @@ -511,7 +511,7 @@ void Ksolve::process( const Eref& e, ProcPtr p ) dsolvePtr_->getBlock( dvalues ); // Second, set the prev_ value in DiffPoolVec dsolvePtr_->setPrev(); - setBlock( dvalues ); + setBlock( dvalues ); } size_t nvPools = pools_.size( ); diff --git a/moose-core/ksolve/OdeSystem.h b/moose-core/ksolve/OdeSystem.h index 0f7e37a64c5eae9f54b5055641528bf98edb24c5..84e2c72fa8ca9bc2b5245a255cdd9bb072df03eb 100644 --- a/moose-core/ksolve/OdeSystem.h +++ b/moose-core/ksolve/OdeSystem.h @@ -10,11 +10,11 @@ #ifndef _ODE_SYSTEM_H #define _ODE_SYSTEM_H -#if USE_BOOST +#if USE_BOOST_ODE #include "BoostSys.h" #elif USE_GSL #include <gsl/gsl_odeiv2.h> -#endif /* ----- not USE_BOOST ----- */ +#endif /* ----- not USE_BOOST_ODE ----- */ class OdeSystem { public: @@ -36,11 +36,11 @@ class OdeSystem { double epsAbs; // Absolute error double epsRel; // Relative error -#if USE_BOOST +#if USE_BOOST_ODE //BoostSys* pBoostSys; BoostSys boostSys; size_t dimension; -#endif /* ----- USE_BOOST ----- */ +#endif /* ----- USE_BOOST_ODE ----- */ }; #endif // _ODE_SYSTEM_H diff --git a/moose-core/ksolve/SteadyStateBoost.cpp b/moose-core/ksolve/SteadyStateBoost.cpp index 98e5b210d3141f89f64c7aaa5aee323872371879..a96439baec7d42630d9fe2441641a2c5c5521bd0 100644 --- a/moose-core/ksolve/SteadyStateBoost.cpp +++ b/moose-core/ksolve/SteadyStateBoost.cpp @@ -339,7 +339,6 @@ SteadyState::SteadyState() solutionStatus_( 0 ), numFailed_( 0 ) { - rng.setSeed( moose::__rng_seed__ ); } SteadyState::~SteadyState() @@ -1046,7 +1045,7 @@ void SteadyState::fitConservationRules( double ytot = 0.0; for ( int k = j; k < lastJ; ++k ) { - y[k] = rng.uniform( ); + y[k] = moose::mtrand(); ytot += y[k] * U( i, k ); } assert( fabs( ytot ) > EPSILON ); diff --git a/moose-core/ksolve/SteadyStateBoost.h b/moose-core/ksolve/SteadyStateBoost.h index 66303a18165037a9ea5cf5869aaa40f4355ca922..7db6b0da8c8d9e5a180a2670a97bca2a7e170bbd 100644 --- a/moose-core/ksolve/SteadyStateBoost.h +++ b/moose-core/ksolve/SteadyStateBoost.h @@ -125,9 +125,7 @@ private: unsigned int numFailed_; VoxelPools pool_; - moose::RNG<double> rng; - -#if USE_BOOST +#if USE_BOOST_ODE NonlinearSystem* ss; #endif diff --git a/moose-core/ksolve/SteadyStateGsl.cpp b/moose-core/ksolve/SteadyStateGsl.cpp index e8d805d7a4d78de23cb1dcb81740715308bf0b4f..295b5256d5edcd4e574ef7b9e99222db4aef9e23 100644 --- a/moose-core/ksolve/SteadyStateGsl.cpp +++ b/moose-core/ksolve/SteadyStateGsl.cpp @@ -18,7 +18,9 @@ * Likewise, if you want to carry out a dose-response calculation. */ -#include "header.h" +#include "../basecode/header.h" +#include "../basecode/global.h" + #include "SparseMatrix.h" #include "KinSparseMatrix.h" #include "RateTerm.h" @@ -28,7 +30,6 @@ #include "XferInfo.h" #include "ZombiePoolInterface.h" #include "Stoich.h" -#include "../randnum/randnum.h" #ifdef USE_GSL #include <gsl/gsl_errno.h> @@ -64,249 +65,250 @@ const double SteadyState::DELTA = 1e-6; */ struct reac_info { - int rank; - int num_reacs; - size_t num_mols; - int nIter; - double convergenceCriterion; + int rank; + int num_reacs; + size_t num_mols; + int nIter; + double convergenceCriterion; - double* T; - VoxelPools* pool; - vector< double > nVec; + double* T; + VoxelPools* pool; + vector< double > nVec; #ifdef USE_GSL - gsl_matrix* Nr; - gsl_matrix* gamma; + gsl_matrix* Nr; + gsl_matrix* gamma; #endif }; const Cinfo* SteadyState::initCinfo() { - /** - * This picks up the entire Stoich data structure - static Finfo* gslShared[] = - { - new SrcFinfo( "reinitSrc", Ftype0::global() ), - new DestFinfo( "assignStoich", - Ftype1< void* >::global(), - RFCAST( &SteadyState::assignStoichFunc ) - ), - new DestFinfo( "setMolN", - Ftype2< double, unsigned int >::global(), - RFCAST( &SteadyState::setMolN ) - ), - new SrcFinfo( "requestYsrc", Ftype0::global() ), - new DestFinfo( "assignY", - Ftype1< double* >::global(), - RFCAST( &SteadyState::assignY ) - ), - }; - */ - - /** - * These are the fields of the SteadyState class - */ - /////////////////////////////////////////////////////// - // Field definitions - /////////////////////////////////////////////////////// - static ValueFinfo< SteadyState, Id > stoich( - "stoich", - "Specify the Id of the stoichiometry system to use", - &SteadyState::setStoich, - &SteadyState::getStoich - ); - static ReadOnlyValueFinfo< SteadyState, bool > badStoichiometry( - "badStoichiometry", - "Bool: True if there is a problem with the stoichiometry", - &SteadyState::badStoichiometry - ); - static ReadOnlyValueFinfo< SteadyState, bool > isInitialized( - "isInitialized", - "True if the model has been initialized successfully", - &SteadyState::isInitialized - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > nIter( - "nIter", - "Number of iterations done by steady state solver", - &SteadyState::getNiter - ); - static ReadOnlyValueFinfo< SteadyState, string > status( - "status", - "Status of solver", - &SteadyState::getStatus - ); - static ValueFinfo< SteadyState, unsigned int > maxIter( - "maxIter", - "Max permissible number of iterations to try before giving up", - &SteadyState::setMaxIter, - &SteadyState::getMaxIter - ); - static ValueFinfo< SteadyState, double> convergenceCriterion( - "convergenceCriterion", - "Fractional accuracy required to accept convergence", - &SteadyState::setConvergenceCriterion, - &SteadyState::getConvergenceCriterion - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > numVarPools( - "numVarPools", - "Number of variable molecules in reaction system.", - &SteadyState::getNumVarPools - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > rank( - "rank", - "Number of independent molecules in reaction system", - &SteadyState::getRank - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > stateType( - "stateType", - "0: stable; 1: unstable; 2: saddle; 3: osc?; 4: one near-zero eigenvalue; 5: other", - &SteadyState::getStateType - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > - nNegEigenvalues ( - "nNegEigenvalues", - "Number of negative eigenvalues: indicates type of solution", - &SteadyState::getNnegEigenvalues - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > - nPosEigenvalues( - "nPosEigenvalues", - "Number of positive eigenvalues: indicates type of solution", - &SteadyState::getNposEigenvalues - ); - static ReadOnlyValueFinfo< SteadyState, unsigned int > solutionStatus( - "solutionStatus", - "0: Good; 1: Failed to find steady states; " - "2: Failed to find eigenvalues", - &SteadyState::getSolutionStatus - ); - static LookupValueFinfo< SteadyState, unsigned int, double > total( - "total", - "Totals table for conservation laws. The exact mapping of" - "this to various sums of molecules is given by the " - "conservation matrix, and is currently a bit opaque." - "The value of 'total' is set to initial conditions when" - "the 'SteadyState::settle' function is called." - "Assigning values to the total is a special operation:" - "it rescales the concentrations of all the affected" - "molecules so that they are at the specified total." - "This happens the next time 'settle' is called.", - &SteadyState::setTotal, - &SteadyState::getTotal - ); - static ReadOnlyLookupValueFinfo< - SteadyState, unsigned int, double > eigenvalues( - "eigenvalues", - "Eigenvalues computed for steady state", - &SteadyState::getEigenvalue - ); - /////////////////////////////////////////////////////// - // MsgDest definitions - /////////////////////////////////////////////////////// - static DestFinfo setupMatrix( "setupMatrix", - "This function initializes and rebuilds the matrices used " - "in the calculation.", - new OpFunc0< SteadyState >(&SteadyState::setupMatrix) - ); - - static DestFinfo settle( "settle", - "Finds the nearest steady state to the current initial " - "conditions. This function rebuilds the entire calculation " - "only if the object has not yet been initialized.", - new OpFunc0< SteadyState >( &SteadyState::settleFunc ) - ); - static DestFinfo resettle( "resettle", - "Finds the nearest steady state to the current initial " - "conditions. This function rebuilds the entire calculation ", - new OpFunc0< SteadyState >( &SteadyState::resettleFunc ) - ); - static DestFinfo showMatrices( "showMatrices", - "Utility function to show the matrices derived for the calculations on the reaction system. Shows the Nr, gamma, and total matrices", - new OpFunc0< SteadyState >( &SteadyState::showMatrices ) - ); - static DestFinfo randomInit( "randomInit", - "Generate random initial conditions consistent with the mass" - "conservation rules. Typically invoked in order to scan" - "states", - new EpFunc0< SteadyState >( - &SteadyState::randomizeInitialCondition ) - ); - /////////////////////////////////////////////////////// - // Shared definitions - /////////////////////////////////////////////////////// - - static Finfo * steadyStateFinfos[] = { - &stoich, // Value - &badStoichiometry, // ReadOnlyValue - &isInitialized, // ReadOnlyValue - &nIter, // ReadOnlyValue - &status, // ReadOnlyValue - &maxIter, // Value - &convergenceCriterion, // ReadOnlyValue - &numVarPools, // ReadOnlyValue - &rank, // ReadOnlyValue - &stateType, // ReadOnlyValue - &nNegEigenvalues, // ReadOnlyValue - &nPosEigenvalues, // ReadOnlyValue - &solutionStatus, // ReadOnlyValue - &total, // LookupValue - &eigenvalues, // ReadOnlyLookupValue - &setupMatrix, // DestFinfo - &settle, // DestFinfo - &resettle, // DestFinfo - &showMatrices, // DestFinfo - &randomInit, // DestFinfo - - - }; - - static string doc[] = - { - "Name", "SteadyState", - "Author", "Upinder S. Bhalla, 2009, updated 2014, NCBS", - "Description", "SteadyState: works out a steady-state value for " - "a reaction system. " - "This class uses the GSL multidimensional root finder algorithms " - "to find the fixed points closest to the " - "current molecular concentrations. " - "When it finds the fixed points, it figures out eigenvalues of " - "the solution, as a way to help classify the fixed points. " - "Note that the method finds unstable as well as stable fixed " - "points.\n " - "The SteadyState class also provides a utility function " - "*randomInit()* to " - "randomly initialize the concentrations, within the constraints " - "of stoichiometry. This is useful if you are trying to find " - "the major fixed points of the system. Note that this is " - "probabilistic. If a fixed point is in a very narrow range of " - "state space the probability of finding it is small and you " - "will have to run many iterations with different initial " - "conditions to find it.\n " - "The numerical calculations used by the SteadyState solver are " - "prone to failing on individual calculations. All is not lost, " - "because the system reports the solutionStatus. " - "It is recommended that you test this field after every " - "calculation, so you can simply ignore " - "cases where it failed and try again with different starting " - "conditions.\n " - "Another rule of thumb is that the SteadyState object is more " - "likely to succeed in finding solutions from a new starting point " - "if you numerically integrate the chemical system for a short " - "time (typically under 1 second) before asking it to find the " - "fixed point. " - }; - - static Dinfo< SteadyState > dinfo; - static Cinfo steadyStateCinfo( - "SteadyState", - Neutral::initCinfo(), - steadyStateFinfos, - sizeof( steadyStateFinfos )/sizeof(Finfo *), - &dinfo, - doc, sizeof( doc ) / sizeof( string ) - ); - - return &steadyStateCinfo; + /** + * This picks up the entire Stoich data structure + static Finfo* gslShared[] = + { + new SrcFinfo( "reinitSrc", Ftype0::global() ), + new DestFinfo( "assignStoich", + Ftype1< void* >::global(), + RFCAST( &SteadyState::assignStoichFunc ) + ), + new DestFinfo( "setMolN", + Ftype2< double, unsigned int >::global(), + RFCAST( &SteadyState::setMolN ) + ), + new SrcFinfo( "requestYsrc", Ftype0::global() ), + new DestFinfo( "assignY", + Ftype1< double* >::global(), + RFCAST( &SteadyState::assignY ) + ), + }; + */ + + /** + * These are the fields of the SteadyState class + */ + /////////////////////////////////////////////////////// + // Field definitions + /////////////////////////////////////////////////////// + static ValueFinfo< SteadyState, Id > stoich( + "stoich", + "Specify the Id of the stoichiometry system to use", + &SteadyState::setStoich, + &SteadyState::getStoich + ); + static ReadOnlyValueFinfo< SteadyState, bool > badStoichiometry( + "badStoichiometry", + "Bool: True if there is a problem with the stoichiometry", + &SteadyState::badStoichiometry + ); + static ReadOnlyValueFinfo< SteadyState, bool > isInitialized( + "isInitialized", + "True if the model has been initialized successfully", + &SteadyState::isInitialized + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > nIter( + "nIter", + "Number of iterations done by steady state solver", + &SteadyState::getNiter + ); + static ReadOnlyValueFinfo< SteadyState, string > status( + "status", + "Status of solver", + &SteadyState::getStatus + ); + static ValueFinfo< SteadyState, unsigned int > maxIter( + "maxIter", + "Max permissible number of iterations to try before giving up", + &SteadyState::setMaxIter, + &SteadyState::getMaxIter + ); + static ValueFinfo< SteadyState, double> convergenceCriterion( + "convergenceCriterion", + "Fractional accuracy required to accept convergence", + &SteadyState::setConvergenceCriterion, + &SteadyState::getConvergenceCriterion + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > numVarPools( + "numVarPools", + "Number of variable molecules in reaction system.", + &SteadyState::getNumVarPools + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > rank( + "rank", + "Number of independent molecules in reaction system", + &SteadyState::getRank + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > stateType( + "stateType", + "0: stable; 1: unstable; 2: saddle; 3: osc?; 4: one near-zero eigenvalue; 5: other", + &SteadyState::getStateType + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > + nNegEigenvalues ( + "nNegEigenvalues", + "Number of negative eigenvalues: indicates type of solution", + &SteadyState::getNnegEigenvalues + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > + nPosEigenvalues( + "nPosEigenvalues", + "Number of positive eigenvalues: indicates type of solution", + &SteadyState::getNposEigenvalues + ); + static ReadOnlyValueFinfo< SteadyState, unsigned int > solutionStatus( + "solutionStatus", + "0: Good; 1: Failed to find steady states; " + "2: Failed to find eigenvalues", + &SteadyState::getSolutionStatus + ); + static LookupValueFinfo< SteadyState, unsigned int, double > total( + "total", + "Totals table for conservation laws. The exact mapping of" + "this to various sums of molecules is given by the " + "conservation matrix, and is currently a bit opaque." + "The value of 'total' is set to initial conditions when" + "the 'SteadyState::settle' function is called." + "Assigning values to the total is a special operation:" + "it rescales the concentrations of all the affected" + "molecules so that they are at the specified total." + "This happens the next time 'settle' is called.", + &SteadyState::setTotal, + &SteadyState::getTotal + ); + static ReadOnlyLookupValueFinfo< + SteadyState, unsigned int, double > eigenvalues( + "eigenvalues", + "Eigenvalues computed for steady state", + &SteadyState::getEigenvalue + ); + /////////////////////////////////////////////////////// + // MsgDest definitions + /////////////////////////////////////////////////////// + static DestFinfo setupMatrix( "setupMatrix", + "This function initializes and rebuilds the matrices used " + "in the calculation.", + new OpFunc0< SteadyState >(&SteadyState::setupMatrix) + ); + + static DestFinfo settle( "settle", + "Finds the nearest steady state to the current initial " + "conditions. This function rebuilds the entire calculation " + "only if the object has not yet been initialized.", + new OpFunc0< SteadyState >( &SteadyState::settleFunc ) + ); + static DestFinfo resettle( "resettle", + "Finds the nearest steady state to the current initial " + "conditions. This function rebuilds the entire calculation ", + new OpFunc0< SteadyState >( &SteadyState::resettleFunc ) + ); + static DestFinfo showMatrices( "showMatrices", + "Utility function to show the matrices derived for the calculations on the reaction system. Shows the Nr, gamma, and total matrices", + new OpFunc0< SteadyState >( &SteadyState::showMatrices ) + ); + static DestFinfo randomInit( "randomInit", + "Generate random initial conditions consistent with the mass" + "conservation rules. Typically invoked in order to scan" + "states", + new EpFunc0< SteadyState >( + &SteadyState::randomizeInitialCondition ) + ); + /////////////////////////////////////////////////////// + // Shared definitions + /////////////////////////////////////////////////////// + + static Finfo * steadyStateFinfos[] = + { + &stoich, // Value + &badStoichiometry, // ReadOnlyValue + &isInitialized, // ReadOnlyValue + &nIter, // ReadOnlyValue + &status, // ReadOnlyValue + &maxIter, // Value + &convergenceCriterion, // ReadOnlyValue + &numVarPools, // ReadOnlyValue + &rank, // ReadOnlyValue + &stateType, // ReadOnlyValue + &nNegEigenvalues, // ReadOnlyValue + &nPosEigenvalues, // ReadOnlyValue + &solutionStatus, // ReadOnlyValue + &total, // LookupValue + &eigenvalues, // ReadOnlyLookupValue + &setupMatrix, // DestFinfo + &settle, // DestFinfo + &resettle, // DestFinfo + &showMatrices, // DestFinfo + &randomInit, // DestFinfo + + + }; + + static string doc[] = + { + "Name", "SteadyState", + "Author", "Upinder S. Bhalla, 2009, updated 2014, NCBS", + "Description", "SteadyState: works out a steady-state value for " + "a reaction system. " + "This class uses the GSL multidimensional root finder algorithms " + "to find the fixed points closest to the " + "current molecular concentrations. " + "When it finds the fixed points, it figures out eigenvalues of " + "the solution, as a way to help classify the fixed points. " + "Note that the method finds unstable as well as stable fixed " + "points.\n " + "The SteadyState class also provides a utility function " + "*randomInit()* to " + "randomly initialize the concentrations, within the constraints " + "of stoichiometry. This is useful if you are trying to find " + "the major fixed points of the system. Note that this is " + "probabilistic. If a fixed point is in a very narrow range of " + "state space the probability of finding it is small and you " + "will have to run many iterations with different initial " + "conditions to find it.\n " + "The numerical calculations used by the SteadyState solver are " + "prone to failing on individual calculations. All is not lost, " + "because the system reports the solutionStatus. " + "It is recommended that you test this field after every " + "calculation, so you can simply ignore " + "cases where it failed and try again with different starting " + "conditions.\n " + "Another rule of thumb is that the SteadyState object is more " + "likely to succeed in finding solutions from a new starting point " + "if you numerically integrate the chemical system for a short " + "time (typically under 1 second) before asking it to find the " + "fixed point. " + }; + + static Dinfo< SteadyState > dinfo; + static Cinfo steadyStateCinfo( + "SteadyState", + Neutral::initCinfo(), + steadyStateFinfos, + sizeof( steadyStateFinfos )/sizeof(Finfo *), + &dinfo, + doc, sizeof( doc ) / sizeof( string ) + ); + + return &steadyStateCinfo; } static const Cinfo* steadyStateCinfo = SteadyState::initCinfo(); @@ -316,42 +318,42 @@ static const Cinfo* steadyStateCinfo = SteadyState::initCinfo(); /////////////////////////////////////////////////// SteadyState::SteadyState() - : - nIter_( 0 ), - maxIter_( 100 ), - badStoichiometry_( 0 ), - status_( "OK" ), - isInitialized_( 0 ), - isSetup_( 0 ), - convergenceCriterion_( 1e-7 ), + : + nIter_( 0 ), + maxIter_( 100 ), + badStoichiometry_( 0 ), + status_( "OK" ), + isInitialized_( 0 ), + isSetup_( 0 ), + convergenceCriterion_( 1e-7 ), #ifdef USE_GSL - LU_( 0 ), - Nr_( 0 ), - gamma_( 0 ), + LU_( 0 ), + Nr_( 0 ), + gamma_( 0 ), #endif - stoich_(), - numVarPools_( 0 ), - nReacs_( 0 ), - rank_( 0 ), - reassignTotal_( 0 ), - nNegEigenvalues_( 0 ), - nPosEigenvalues_( 0 ), - stateType_( 0 ), - solutionStatus_( 0 ), - numFailed_( 0 ) + stoich_(), + numVarPools_( 0 ), + nReacs_( 0 ), + rank_( 0 ), + reassignTotal_( 0 ), + nNegEigenvalues_( 0 ), + nPosEigenvalues_( 0 ), + stateType_( 0 ), + solutionStatus_( 0 ), + numFailed_( 0 ) { - ; + ; } SteadyState::~SteadyState() { #ifdef USE_GSL - if ( LU_ != 0 ) - gsl_matrix_free( LU_ ); - if ( Nr_ != 0 ) - gsl_matrix_free( Nr_ ); - if ( gamma_ != 0 ) - gsl_matrix_free( gamma_ ); + if ( LU_ != 0 ) + gsl_matrix_free( LU_ ); + if ( Nr_ != 0 ) + gsl_matrix_free( Nr_ ); + if ( gamma_ != 0 ) + gsl_matrix_free( gamma_ ); #endif } @@ -359,118 +361,136 @@ SteadyState::~SteadyState() // Field function definitions /////////////////////////////////////////////////// -Id SteadyState::getStoich() const { - return stoich_; +Id SteadyState::getStoich() const +{ + return stoich_; } -void SteadyState::setStoich( Id value ) { - if ( !value.element()->cinfo()->isA( "Stoich" ) ) { - cout << "Error: SteadyState::setStoich: Must be of Stoich class\n"; - return; - } - - stoich_ = value; - Stoich* stoichPtr = reinterpret_cast< Stoich* >( value.eref().data()); - numVarPools_ = Field< unsigned int >::get( stoich_, "numVarPools" ); - nReacs_ = Field< unsigned int >::get( stoich_, "numRates" ); - setupSSmatrix(); - double vol = LookupField< unsigned int, double >::get( - stoichPtr->getCompartment(), "oneVoxelVolume", 0 ); - pool_.setVolume( vol ); - pool_.setStoich( stoichPtr, 0 ); - pool_.updateAllRateTerms( stoichPtr->getRateTerms(), - stoichPtr->getNumCoreRates() ); - isInitialized_ = 1; +void SteadyState::setStoich( Id value ) +{ + if ( !value.element()->cinfo()->isA( "Stoich" ) ) + { + cout << "Error: SteadyState::setStoich: Must be of Stoich class\n"; + return; + } + + stoich_ = value; + Stoich* stoichPtr = reinterpret_cast< Stoich* >( value.eref().data()); + numVarPools_ = Field< unsigned int >::get( stoich_, "numVarPools" ); + nReacs_ = Field< unsigned int >::get( stoich_, "numRates" ); + setupSSmatrix(); + double vol = LookupField< unsigned int, double >::get( + stoichPtr->getCompartment(), "oneVoxelVolume", 0 ); + pool_.setVolume( vol ); + pool_.setStoich( stoichPtr, 0 ); + pool_.updateAllRateTerms( stoichPtr->getRateTerms(), + stoichPtr->getNumCoreRates() ); + isInitialized_ = 1; } -bool SteadyState::badStoichiometry() const { - return badStoichiometry_; +bool SteadyState::badStoichiometry() const +{ + return badStoichiometry_; } -bool SteadyState::isInitialized() const { - return isInitialized_; +bool SteadyState::isInitialized() const +{ + return isInitialized_; } -unsigned int SteadyState::getNiter() const { - return nIter_; +unsigned int SteadyState::getNiter() const +{ + return nIter_; } -string SteadyState::getStatus() const { - return status_; +string SteadyState::getStatus() const +{ + return status_; } -unsigned int SteadyState::getMaxIter() const { - return maxIter_; +unsigned int SteadyState::getMaxIter() const +{ + return maxIter_; } -void SteadyState::setMaxIter( unsigned int value ) { - maxIter_ = value; +void SteadyState::setMaxIter( unsigned int value ) +{ + maxIter_ = value; } -unsigned int SteadyState::getRank() const { - return rank_; +unsigned int SteadyState::getRank() const +{ + return rank_; } -unsigned int SteadyState::getNumVarPools() const { - return numVarPools_; +unsigned int SteadyState::getNumVarPools() const +{ + return numVarPools_; } -unsigned int SteadyState::getStateType() const { - return stateType_; +unsigned int SteadyState::getStateType() const +{ + return stateType_; } -unsigned int SteadyState::getNnegEigenvalues() const { - return nNegEigenvalues_; +unsigned int SteadyState::getNnegEigenvalues() const +{ + return nNegEigenvalues_; } -unsigned int SteadyState::getNposEigenvalues() const { - return nPosEigenvalues_; +unsigned int SteadyState::getNposEigenvalues() const +{ + return nPosEigenvalues_; } -unsigned int SteadyState::getSolutionStatus() const { - return solutionStatus_; +unsigned int SteadyState::getSolutionStatus() const +{ + return solutionStatus_; } -void SteadyState::setConvergenceCriterion( double value ) { - if ( value > 1e-10 ) - convergenceCriterion_ = value; - else - cout << "Warning: Convergence criterion " << value << - " too small. Old value " << - convergenceCriterion_ << " retained\n"; +void SteadyState::setConvergenceCriterion( double value ) +{ + if ( value > 1e-10 ) + convergenceCriterion_ = value; + else + cout << "Warning: Convergence criterion " << value << + " too small. Old value " << + convergenceCriterion_ << " retained\n"; } -double SteadyState::getConvergenceCriterion() const { - return convergenceCriterion_; +double SteadyState::getConvergenceCriterion() const +{ + return convergenceCriterion_; } double SteadyState::getTotal( const unsigned int i ) const { - if ( i < total_.size() ) - return total_[i]; - cout << "Warning: SteadyState::getTotal: index " << i << - " out of range " << total_.size() << endl; - return 0.0; + if ( i < total_.size() ) + return total_[i]; + cout << "Warning: SteadyState::getTotal: index " << i << + " out of range " << total_.size() << endl; + return 0.0; } void SteadyState::setTotal( const unsigned int i, double val ) { - if ( i < total_.size() ) { - total_[i] = val; - reassignTotal_ = 1; - return; - } - cout << "Warning: SteadyState::setTotal: index " << i << - " out of range " << total_.size() << endl; + if ( i < total_.size() ) + { + total_[i] = val; + reassignTotal_ = 1; + return; + } + cout << "Warning: SteadyState::setTotal: index " << i << + " out of range " << total_.size() << endl; } double SteadyState::getEigenvalue( const unsigned int i ) const { - if ( i < eigenvalues_.size() ) - return eigenvalues_[i]; - cout << "Warning: SteadyState::getEigenvalue: index " << i << - " out of range " << eigenvalues_.size() << endl; - return 0.0; + if ( i < eigenvalues_.size() ) + return eigenvalues_[i]; + cout << "Warning: SteadyState::getEigenvalue: index " << i << + " out of range " << eigenvalues_.size() << endl; + return 0.0; } /////////////////////////////////////////////////// @@ -480,16 +500,16 @@ double SteadyState::getEigenvalue( const unsigned int i ) const // Static func void SteadyState::setupMatrix() { - setupSSmatrix(); + setupSSmatrix(); } void SteadyState::settleFunc() { - settle( 0 ); + settle( 0 ); } void SteadyState::resettleFunc() { - settle( 1 ); + settle( 1 ); } // Dummy function @@ -506,8 +526,10 @@ void print_gsl_mat( gsl_matrix* m, const char* name ) { size_t i, j; printf( "%s[%lu, %lu] = \n", name, m->size1, m->size2 ); - for (i = 0; i < m->size1; i++) { - for (j = 0; j < m->size2; j++) { + for (i = 0; i < m->size1; i++) + { + for (j = 0; j < m->size2; j++) + { double x = gsl_matrix_get (m, i, j ); if ( fabs( x ) < 1e-9 ) x = 0; printf( "%6g", x ); @@ -520,129 +542,140 @@ void print_gsl_mat( gsl_matrix* m, const char* name ) void SteadyState::showMatrices() { - if ( !isInitialized_ ) { - cout << "SteadyState::showMatrices: Sorry, the system is not yet initialized.\n"; - return; - } - int numConsv = numVarPools_ - rank_; - cout << "Totals: "; - for ( int i = 0; i < numConsv; ++i ) - cout << total_[i] << " "; - cout << endl; + if ( !isInitialized_ ) + { + cout << "SteadyState::showMatrices: Sorry, the system is not yet initialized.\n"; + return; + } + int numConsv = numVarPools_ - rank_; + cout << "Totals: "; + for ( int i = 0; i < numConsv; ++i ) + cout << total_[i] << " "; + cout << endl; #ifdef USE_GSL - print_gsl_mat( gamma_, "gamma" ); - print_gsl_mat( Nr_, "Nr" ); - print_gsl_mat( LU_, "LU" ); + print_gsl_mat( gamma_, "gamma" ); + print_gsl_mat( Nr_, "Nr" ); + print_gsl_mat( LU_, "LU" ); #endif } void SteadyState::setupSSmatrix() { #ifdef USE_GSL - if ( numVarPools_ == 0 || nReacs_ == 0 ) - return; - - int nTot = numVarPools_ + nReacs_; - gsl_matrix* N = gsl_matrix_calloc (numVarPools_, nReacs_); - if ( LU_ ) { // Clear out old one. - gsl_matrix_free( LU_ ); - } - LU_ = gsl_matrix_calloc (numVarPools_, nTot); - vector< int > entry = Field< vector< int > >::get( - stoich_, "matrixEntry" ); - vector< unsigned int > colIndex = Field< vector< unsigned int > >::get( - stoich_, "columnIndex" ); - vector< unsigned int > rowStart = Field< vector< unsigned int > >::get( - stoich_, "rowStart" ); - - // cout << endl << endl; - for ( unsigned int i = 0; i < numVarPools_; ++i ) { - gsl_matrix_set (LU_, i, i + nReacs_, 1 ); - unsigned int k = rowStart[i]; - // cout << endl << i << ": "; - for ( unsigned int j = 0; j < nReacs_; ++j ) { - double x = 0; - if ( j == colIndex[k] && k < rowStart[i+1] ) { - x = entry[k++]; - } - // cout << " " << x; - gsl_matrix_set (N, i, j, x); - gsl_matrix_set (LU_, i, j, x ); - } - } - cout << endl << endl; - - rank_ = myGaussianDecomp( LU_ ); - - unsigned int nConsv = numVarPools_ - rank_; - if ( nConsv == 0 ) { - cout << "SteadyState::setupSSmatrix(): Number of conserved species == 0. Aborting\n"; - return; - } - - if ( Nr_ ) { // Clear out old one. - gsl_matrix_free( Nr_ ); - } - Nr_ = gsl_matrix_calloc ( rank_, nReacs_ ); - // Fill up Nr. - for ( unsigned int i = 0; i < rank_; i++) - for ( unsigned int j = i; j < nReacs_; j++) - gsl_matrix_set (Nr_, i, j, gsl_matrix_get( LU_, i, j ) ); - - if ( gamma_ ) { // Clear out old one. - gsl_matrix_free( gamma_ ); - } - gamma_ = gsl_matrix_calloc (nConsv, numVarPools_ ); - - // Fill up gamma - for ( unsigned int i = rank_; i < numVarPools_; ++i ) - for ( unsigned int j = 0; j < numVarPools_; ++j ) - gsl_matrix_set( gamma_, i - rank_, j, - gsl_matrix_get( LU_, i, j + nReacs_ ) ); - - // Fill up boundary condition values - total_.resize( nConsv ); - total_.assign( nConsv, 0.0 ); - - /* - cout << "S = ("; - for ( unsigned int j = 0; j < numVarPools_; ++j ) - cout << s_->S()[ j ] << ", "; - cout << "), Sinit = ( "; - for ( unsigned int j = 0; j < numVarPools_; ++j ) - cout << s_->Sinit()[ j ] << ", "; - cout << ")\n"; - */ - Id ksolve = Field< Id >::get( stoich_, "ksolve" ); - vector< double > nVec = - LookupField< unsigned int, vector< double > >::get( - ksolve,"nVec", 0 ); - - if ( nVec.size() >= numVarPools_ ) { - for ( unsigned int i = 0; i < nConsv; ++i ) - for ( unsigned int j = 0; j < numVarPools_; ++j ) - total_[i] += gsl_matrix_get( gamma_, i, j ) * nVec[ j ]; - isSetup_ = 1; - } else { - cout << "Error: SteadyState::setupSSmatrix(): unable to get" - "pool numbers from ksolve.\n"; - isSetup_ = 0; - } - - gsl_matrix_free( N ); + if ( numVarPools_ == 0 || nReacs_ == 0 ) + return; + + int nTot = numVarPools_ + nReacs_; + gsl_matrix* N = gsl_matrix_calloc (numVarPools_, nReacs_); + if ( LU_ ) // Clear out old one. + { + gsl_matrix_free( LU_ ); + } + LU_ = gsl_matrix_calloc (numVarPools_, nTot); + vector< int > entry = Field< vector< int > >::get( + stoich_, "matrixEntry" ); + vector< unsigned int > colIndex = Field< vector< unsigned int > >::get( + stoich_, "columnIndex" ); + vector< unsigned int > rowStart = Field< vector< unsigned int > >::get( + stoich_, "rowStart" ); + + // cout << endl << endl; + for ( unsigned int i = 0; i < numVarPools_; ++i ) + { + gsl_matrix_set (LU_, i, i + nReacs_, 1 ); + unsigned int k = rowStart[i]; + // cout << endl << i << ": "; + for ( unsigned int j = 0; j < nReacs_; ++j ) + { + double x = 0; + if ( j == colIndex[k] && k < rowStart[i+1] ) + { + x = entry[k++]; + } + // cout << " " << x; + gsl_matrix_set (N, i, j, x); + gsl_matrix_set (LU_, i, j, x ); + } + } + cout << endl << endl; + + rank_ = myGaussianDecomp( LU_ ); + + unsigned int nConsv = numVarPools_ - rank_; + if ( nConsv == 0 ) + { + cout << "SteadyState::setupSSmatrix(): Number of conserved species == 0. Aborting\n"; + return; + } + + if ( Nr_ ) // Clear out old one. + { + gsl_matrix_free( Nr_ ); + } + Nr_ = gsl_matrix_calloc ( rank_, nReacs_ ); + // Fill up Nr. + for ( unsigned int i = 0; i < rank_; i++) + for ( unsigned int j = i; j < nReacs_; j++) + gsl_matrix_set (Nr_, i, j, gsl_matrix_get( LU_, i, j ) ); + + if ( gamma_ ) // Clear out old one. + { + gsl_matrix_free( gamma_ ); + } + gamma_ = gsl_matrix_calloc (nConsv, numVarPools_ ); + + // Fill up gamma + for ( unsigned int i = rank_; i < numVarPools_; ++i ) + for ( unsigned int j = 0; j < numVarPools_; ++j ) + gsl_matrix_set( gamma_, i - rank_, j, + gsl_matrix_get( LU_, i, j + nReacs_ ) ); + + // Fill up boundary condition values + total_.resize( nConsv ); + total_.assign( nConsv, 0.0 ); + + /* + cout << "S = ("; + for ( unsigned int j = 0; j < numVarPools_; ++j ) + cout << s_->S()[ j ] << ", "; + cout << "), Sinit = ( "; + for ( unsigned int j = 0; j < numVarPools_; ++j ) + cout << s_->Sinit()[ j ] << ", "; + cout << ")\n"; + */ + Id ksolve = Field< Id >::get( stoich_, "ksolve" ); + vector< double > nVec = + LookupField< unsigned int, vector< double > >::get( + ksolve,"nVec", 0 ); + + if ( nVec.size() >= numVarPools_ ) + { + for ( unsigned int i = 0; i < nConsv; ++i ) + for ( unsigned int j = 0; j < numVarPools_; ++j ) + total_[i] += gsl_matrix_get( gamma_, i, j ) * nVec[ j ]; + isSetup_ = 1; + } + else + { + cout << "Error: SteadyState::setupSSmatrix(): unable to get" + "pool numbers from ksolve.\n"; + isSetup_ = 0; + } + + gsl_matrix_free( N ); #endif } static double op( double x ) { - return x * x; + return x * x; } static double invop( double x ) { - if ( x > 0.0 ) - return sqrt( x ); - return 0.0; + if ( x > 0.0 ) + return sqrt( x ); + return 0.0; } @@ -654,140 +687,153 @@ static double invop( double x ) */ #ifdef USE_GSL int iterate( const gsl_multiroot_fsolver_type* st, struct reac_info *ri, - int maxIter ) + int maxIter ) { - int status = 0; - gsl_vector* x = gsl_vector_calloc( ri->num_mols ); - gsl_multiroot_fsolver *solver = - gsl_multiroot_fsolver_alloc( st, ri->num_mols ); - gsl_multiroot_function func = {&ss_func, ri->num_mols, ri}; - - // This gives the starting point for finding the solution - for ( unsigned int i = 0; i < ri->num_mols; ++i ) - gsl_vector_set( x, i, invop( ri->nVec[i] ) ); - - gsl_multiroot_fsolver_set( solver, &func, x ); - - ri->nIter = 0; - do { - ri->nIter++; - status = gsl_multiroot_fsolver_iterate( solver ); - if (status ) break; - status = gsl_multiroot_test_residual( - solver->f, ri->convergenceCriterion); - } while (status == GSL_CONTINUE && ri->nIter < maxIter ); - - gsl_multiroot_fsolver_free( solver ); - gsl_vector_free( x ); - return status; + int status = 0; + gsl_vector* x = gsl_vector_calloc( ri->num_mols ); + gsl_multiroot_fsolver *solver = + gsl_multiroot_fsolver_alloc( st, ri->num_mols ); + gsl_multiroot_function func = {&ss_func, ri->num_mols, ri}; + + // This gives the starting point for finding the solution + for ( unsigned int i = 0; i < ri->num_mols; ++i ) + gsl_vector_set( x, i, invop( ri->nVec[i] ) ); + + gsl_multiroot_fsolver_set( solver, &func, x ); + + ri->nIter = 0; + do + { + ri->nIter++; + status = gsl_multiroot_fsolver_iterate( solver ); + if (status ) break; + status = gsl_multiroot_test_residual( + solver->f, ri->convergenceCriterion); + } + while (status == GSL_CONTINUE && ri->nIter < maxIter ); + + gsl_multiroot_fsolver_free( solver ); + gsl_vector_free( x ); + return status; } #endif void SteadyState::classifyState( const double* T ) { #ifdef USE_GSL - // unsigned int nConsv = numVarPools_ - rank_; - gsl_matrix* J = gsl_matrix_calloc ( numVarPools_, numVarPools_ ); - // double* yprime = new double[ numVarPools_ ]; - // vector< double > yprime( numVarPools_, 0.0 ); - // Generate an approximation to the Jacobean by generating small - // increments to each of the molecules in the steady state, one - // at a time, and putting the resultant rate vector into a column - // of the J matrix. - // This needs a bit of heuristic to decide what is a 'small' increment. - // Use the CoInits for this. Stoichiometry shouldn't matter too much. - // I used the totals from consv rules earlier, but that can have - // negative values. - double tot = 0.0; - Stoich* s = reinterpret_cast< Stoich* >( stoich_.eref().data() ); - vector< double > nVec = LookupField< unsigned int, vector< double > >::get( - s->getKsolve(), "nVec", 0 ); - for ( unsigned int i = 0; i < numVarPools_; ++i ) { - tot += nVec[i]; - } - tot *= DELTA; - - vector< double > yprime( nVec.size(), 0.0 ); - // Fill up Jacobian - for ( unsigned int i = 0; i < numVarPools_; ++i ) { - double orig = nVec[i]; - if ( isNaN( orig ) ) { - cout << "Warning: SteadyState::classifyState: orig=nan\n"; - solutionStatus_ = 2; // Steady state OK, eig failed - gsl_matrix_free ( J ); - return; - } - if ( isNaN( tot ) ) { - cout << "Warning: SteadyState::classifyState: tot=nan\n"; - solutionStatus_ = 2; // Steady state OK, eig failed - gsl_matrix_free ( J ); - return; - } - nVec[i] = orig + tot; - - pool_.updateRates( &nVec[0], &yprime[0] ); - nVec[i] = orig; - - // Assign the rates for each mol. - for ( unsigned int j = 0; j < numVarPools_; ++j ) { - gsl_matrix_set( J, i, j, yprime[j] ); - } - } - - // Jacobian is now ready. Find eigenvalues. - gsl_vector_complex* vec = gsl_vector_complex_alloc( numVarPools_ ); - gsl_eigen_nonsymm_workspace* workspace = - gsl_eigen_nonsymm_alloc( numVarPools_ ); - int status = gsl_eigen_nonsymm( J, vec, workspace ); - eigenvalues_.clear(); - eigenvalues_.resize( numVarPools_, 0.0 ); - if ( status != GSL_SUCCESS ) { - cout << "Warning: SteadyState::classifyState failed to find eigenvalues. Status = " << - status << endl; - solutionStatus_ = 2; // Steady state OK, eig classification failed - } else { // Eigenvalues are ready. Classify state. - nNegEigenvalues_ = 0; - nPosEigenvalues_ = 0; - for ( unsigned int i = 0; i < numVarPools_; ++i ) { - gsl_complex z = gsl_vector_complex_get( vec, i ); - double r = GSL_REAL( z ); - nNegEigenvalues_ += ( r < -EPSILON ); - nPosEigenvalues_ += ( r > EPSILON ); - eigenvalues_[i] = r; - // We have a problem here because numVarPools_ usually > rank - // This means we have several zero eigenvalues. - } - - if ( nNegEigenvalues_ == rank_ ) - stateType_ = 0; // Stable - else if ( nPosEigenvalues_ == rank_ ) // Never see it. - stateType_ = 1; // Unstable - else if (nPosEigenvalues_ == 1) - stateType_ = 2; // Saddle - else if ( nPosEigenvalues_ >= 2 ) - stateType_ = 3; // putative oscillatory - else if ( nNegEigenvalues_ == ( rank_ - 1) && nPosEigenvalues_ == 0 ) - stateType_ = 4; // one zero or unclassified eigenvalue. Messy. - else - stateType_ = 5; // Other - } - - gsl_vector_complex_free( vec ); - gsl_matrix_free ( J ); - gsl_eigen_nonsymm_free( workspace ); + // unsigned int nConsv = numVarPools_ - rank_; + gsl_matrix* J = gsl_matrix_calloc ( numVarPools_, numVarPools_ ); + // double* yprime = new double[ numVarPools_ ]; + // vector< double > yprime( numVarPools_, 0.0 ); + // Generate an approximation to the Jacobean by generating small + // increments to each of the molecules in the steady state, one + // at a time, and putting the resultant rate vector into a column + // of the J matrix. + // This needs a bit of heuristic to decide what is a 'small' increment. + // Use the CoInits for this. Stoichiometry shouldn't matter too much. + // I used the totals from consv rules earlier, but that can have + // negative values. + double tot = 0.0; + Stoich* s = reinterpret_cast< Stoich* >( stoich_.eref().data() ); + vector< double > nVec = LookupField< unsigned int, vector< double > >::get( + s->getKsolve(), "nVec", 0 ); + for ( unsigned int i = 0; i < numVarPools_; ++i ) + { + tot += nVec[i]; + } + tot *= DELTA; + + vector< double > yprime( nVec.size(), 0.0 ); + // Fill up Jacobian + for ( unsigned int i = 0; i < numVarPools_; ++i ) + { + double orig = nVec[i]; + if ( isNaN( orig ) ) + { + cout << "Warning: SteadyState::classifyState: orig=nan\n"; + solutionStatus_ = 2; // Steady state OK, eig failed + gsl_matrix_free ( J ); + return; + } + if ( isNaN( tot ) ) + { + cout << "Warning: SteadyState::classifyState: tot=nan\n"; + solutionStatus_ = 2; // Steady state OK, eig failed + gsl_matrix_free ( J ); + return; + } + nVec[i] = orig + tot; + + pool_.updateRates( &nVec[0], &yprime[0] ); + nVec[i] = orig; + + // Assign the rates for each mol. + for ( unsigned int j = 0; j < numVarPools_; ++j ) + { + gsl_matrix_set( J, i, j, yprime[j] ); + } + } + + // Jacobian is now ready. Find eigenvalues. + gsl_vector_complex* vec = gsl_vector_complex_alloc( numVarPools_ ); + gsl_eigen_nonsymm_workspace* workspace = + gsl_eigen_nonsymm_alloc( numVarPools_ ); + int status = gsl_eigen_nonsymm( J, vec, workspace ); + eigenvalues_.clear(); + eigenvalues_.resize( numVarPools_, 0.0 ); + if ( status != GSL_SUCCESS ) + { + cout << "Warning: SteadyState::classifyState failed to find eigenvalues. Status = " << + status << endl; + solutionStatus_ = 2; // Steady state OK, eig classification failed + } + else // Eigenvalues are ready. Classify state. + { + nNegEigenvalues_ = 0; + nPosEigenvalues_ = 0; + for ( unsigned int i = 0; i < numVarPools_; ++i ) + { + gsl_complex z = gsl_vector_complex_get( vec, i ); + double r = GSL_REAL( z ); + nNegEigenvalues_ += ( r < -EPSILON ); + nPosEigenvalues_ += ( r > EPSILON ); + eigenvalues_[i] = r; + // We have a problem here because numVarPools_ usually > rank + // This means we have several zero eigenvalues. + } + + if ( nNegEigenvalues_ == rank_ ) + stateType_ = 0; // Stable + else if ( nPosEigenvalues_ == rank_ ) // Never see it. + stateType_ = 1; // Unstable + else if (nPosEigenvalues_ == 1) + stateType_ = 2; // Saddle + else if ( nPosEigenvalues_ >= 2 ) + stateType_ = 3; // putative oscillatory + else if ( nNegEigenvalues_ == ( rank_ - 1) && nPosEigenvalues_ == 0 ) + stateType_ = 4; // one zero or unclassified eigenvalue. Messy. + else + stateType_ = 5; // Other + } + + gsl_vector_complex_free( vec ); + gsl_matrix_free ( J ); + gsl_eigen_nonsymm_free( workspace ); #endif } static bool isSolutionPositive( const vector< double >& x ) { - for ( vector< double >::const_iterator - i = x.begin(); i != x.end(); ++i ) { - if ( *i < 0.0 ) { - cout << "Warning: SteadyState iteration gave negative concs\n"; - return false; - } - } - return true; + for ( vector< double >::const_iterator + i = x.begin(); i != x.end(); ++i ) + { + if ( *i < 0.0 ) + { + cout << "Warning: SteadyState iteration gave negative concs\n"; + return false; + } + } + return true; } /** @@ -797,76 +843,84 @@ static bool isSolutionPositive( const vector< double >& x ) void SteadyState::settle( bool forceSetup ) { #ifdef USE_GSL - gsl_set_error_handler_off(); - - if ( !isInitialized_ ) { - cout << "Error: SteadyState object has not been initialized. No calculations done\n"; - return; - } - if ( forceSetup || isSetup_ == 0 ) { - setupSSmatrix(); - } - - // Setting up matrices and vectors for the calculation. - unsigned int nConsv = numVarPools_ - rank_; - double * T = (double *) calloc( nConsv, sizeof( double ) ); - - unsigned int i, j; - - - Id ksolve = Field< Id >::get( stoich_, "ksolve" ); - struct reac_info ri; - ri.rank = rank_; - ri.num_reacs = nReacs_; - ri.num_mols = numVarPools_; - ri.T = T; - ri.Nr = Nr_; - ri.gamma = gamma_; - ri.pool = &pool_; - ri.nVec = - LookupField< unsigned int, vector< double > >::get( - ksolve,"nVec", 0 ); - ri.convergenceCriterion = convergenceCriterion_; - - // Fill up boundary condition values - if ( reassignTotal_ ) { // The user has defined new conservation values. - for ( i = 0; i < nConsv; ++i ) - T[i] = total_[i]; - reassignTotal_ = 0; - } else { - for ( i = 0; i < nConsv; ++i ) - for ( j = 0; j < numVarPools_; ++j ) - T[i] += gsl_matrix_get( gamma_, i, j ) * ri.nVec[ j ]; - total_.assign( T, T + nConsv ); - } - - vector< double > repair( numVarPools_, 0.0 ); - for ( unsigned int j = 0; j < numVarPools_; ++j ) - repair[j] = ri.nVec[j]; - - int status = iterate( gsl_multiroot_fsolver_hybrids, &ri, maxIter_ ); - if ( status ) // It failed. Fall back with the Newton method - status = iterate( gsl_multiroot_fsolver_dnewton, &ri, maxIter_ ); - status_ = string( gsl_strerror( status ) ); - nIter_ = ri.nIter; - if ( status == GSL_SUCCESS && isSolutionPositive( ri.nVec ) ) { - solutionStatus_ = 0; // Good solution - LookupField< unsigned int, vector< double > >::set( - ksolve,"nVec", 0, ri.nVec ); - classifyState( T ); - } else { - cout << "Warning: SteadyState iteration failed, status = " << - status_ << ", nIter = " << nIter_ << endl; - // Repair the mess - for ( unsigned int j = 0; j < numVarPools_; ++j ) - ri.nVec[j] = repair[j]; - solutionStatus_ = 1; // Steady state failed. - LookupField< unsigned int, vector< double > >::set( - ksolve,"nVec", 0, ri.nVec ); - } - - // Clean up. - free( T ); + gsl_set_error_handler_off(); + + if ( !isInitialized_ ) + { + cout << "Error: SteadyState object has not been initialized. No calculations done\n"; + return; + } + if ( forceSetup || isSetup_ == 0 ) + { + setupSSmatrix(); + } + + // Setting up matrices and vectors for the calculation. + unsigned int nConsv = numVarPools_ - rank_; + double * T = (double *) calloc( nConsv, sizeof( double ) ); + + unsigned int i, j; + + + Id ksolve = Field< Id >::get( stoich_, "ksolve" ); + struct reac_info ri; + ri.rank = rank_; + ri.num_reacs = nReacs_; + ri.num_mols = numVarPools_; + ri.T = T; + ri.Nr = Nr_; + ri.gamma = gamma_; + ri.pool = &pool_; + ri.nVec = + LookupField< unsigned int, vector< double > >::get( + ksolve,"nVec", 0 ); + ri.convergenceCriterion = convergenceCriterion_; + + // Fill up boundary condition values + if ( reassignTotal_ ) // The user has defined new conservation values. + { + for ( i = 0; i < nConsv; ++i ) + T[i] = total_[i]; + reassignTotal_ = 0; + } + else + { + for ( i = 0; i < nConsv; ++i ) + for ( j = 0; j < numVarPools_; ++j ) + T[i] += gsl_matrix_get( gamma_, i, j ) * ri.nVec[ j ]; + total_.assign( T, T + nConsv ); + } + + vector< double > repair( numVarPools_, 0.0 ); + for ( unsigned int j = 0; j < numVarPools_; ++j ) + repair[j] = ri.nVec[j]; + + int status = iterate( gsl_multiroot_fsolver_hybrids, &ri, maxIter_ ); + if ( status ) // It failed. Fall back with the Newton method + status = iterate( gsl_multiroot_fsolver_dnewton, &ri, maxIter_ ); + status_ = string( gsl_strerror( status ) ); + nIter_ = ri.nIter; + if ( status == GSL_SUCCESS && isSolutionPositive( ri.nVec ) ) + { + solutionStatus_ = 0; // Good solution + LookupField< unsigned int, vector< double > >::set( + ksolve,"nVec", 0, ri.nVec ); + classifyState( T ); + } + else + { + cout << "Warning: SteadyState iteration failed, status = " << + status_ << ", nIter = " << nIter_ << endl; + // Repair the mess + for ( unsigned int j = 0; j < numVarPools_; ++j ) + ri.nVec[j] = repair[j]; + solutionStatus_ = 1; // Steady state failed. + LookupField< unsigned int, vector< double > >::set( + ksolve,"nVec", 0, ri.nVec ); + } + + // Clean up. + free( T ); #endif } @@ -874,42 +928,48 @@ void SteadyState::settle( bool forceSetup ) #ifdef USE_GSL int ss_func( const gsl_vector* x, void* params, gsl_vector* f ) { - struct reac_info* ri = (struct reac_info *)params; - // Stoich* s = reinterpret_cast< Stoich* >( ri->stoich.eref().data() ); - int num_consv = ri->num_mols - ri->rank; - - for ( unsigned int i = 0; i < ri->num_mols; ++i ) { - double temp = op( gsl_vector_get( x, i ) ); - if ( isNaN( temp ) || isInfinity( temp ) ) { - return GSL_ERANGE; - } else { - ri->nVec[i] = temp; - } - } - vector< double > vels; - ri->pool->updateReacVelocities( &ri->nVec[0], vels ); - assert( vels.size() == static_cast< unsigned int >( ri->num_reacs ) ); - - // y = Nr . v - // Note that Nr is row-echelon: diagonal and above. - for ( int i = 0; i < ri->rank; ++i ) { - double temp = 0; - for ( int j = i; j < ri->num_reacs; ++j ) - temp += gsl_matrix_get( ri->Nr, i, j ) * vels[j]; - gsl_vector_set( f, i, temp ); - } - - // dT = gamma.S - T - for ( int i = 0; i < num_consv; ++i ) { - double dT = - ri->T[i]; - for ( unsigned int j = 0; j < ri->num_mols; ++j ) - dT += gsl_matrix_get( ri->gamma, i, j) * - op( gsl_vector_get( x, j ) ); - - gsl_vector_set( f, i + ri->rank, dT ); - } - - return GSL_SUCCESS; + struct reac_info* ri = (struct reac_info *)params; + // Stoich* s = reinterpret_cast< Stoich* >( ri->stoich.eref().data() ); + int num_consv = ri->num_mols - ri->rank; + + for ( unsigned int i = 0; i < ri->num_mols; ++i ) + { + double temp = op( gsl_vector_get( x, i ) ); + if ( isNaN( temp ) || isInfinity( temp ) ) + { + return GSL_ERANGE; + } + else + { + ri->nVec[i] = temp; + } + } + vector< double > vels; + ri->pool->updateReacVelocities( &ri->nVec[0], vels ); + assert( vels.size() == static_cast< unsigned int >( ri->num_reacs ) ); + + // y = Nr . v + // Note that Nr is row-echelon: diagonal and above. + for ( int i = 0; i < ri->rank; ++i ) + { + double temp = 0; + for ( int j = i; j < ri->num_reacs; ++j ) + temp += gsl_matrix_get( ri->Nr, i, j ) * vels[j]; + gsl_vector_set( f, i, temp ); + } + + // dT = gamma.S - T + for ( int i = 0; i < num_consv; ++i ) + { + double dT = - ri->T[i]; + for ( unsigned int j = 0; j < ri->num_mols; ++j ) + dT += gsl_matrix_get( ri->gamma, i, j) * + op( gsl_vector_get( x, j ) ); + + gsl_vector_set( f, i + ri->rank, dT ); + } + + return GSL_SUCCESS; } /** @@ -923,24 +983,27 @@ int ss_func( const gsl_vector* x, void* params, gsl_vector* f ) */ void eliminateRowsBelow( gsl_matrix* U, int start, int leftCol ) { - int numMols = U->size1; - double pivot = gsl_matrix_get( U, start, leftCol ); - assert( fabs( pivot ) > SteadyState::EPSILON ); - for ( int i = start + 1; i < numMols; ++i ) { - double factor = gsl_matrix_get( U, i, leftCol ); - if ( fabs ( factor ) > SteadyState::EPSILON ) { - factor = factor / pivot; - for ( size_t j = leftCol + 1; j < U->size2; ++j ) { - double x = gsl_matrix_get( U, i, j ); - double y = gsl_matrix_get( U, start, j ); - x -= y * factor; - if ( fabs( x ) < SteadyState::EPSILON ) - x = 0.0; - gsl_matrix_set( U, i, j, x ); - } - } - gsl_matrix_set( U, i, leftCol, 0.0 ); // Cleaning up. - } + int numMols = U->size1; + double pivot = gsl_matrix_get( U, start, leftCol ); + assert( fabs( pivot ) > SteadyState::EPSILON ); + for ( int i = start + 1; i < numMols; ++i ) + { + double factor = gsl_matrix_get( U, i, leftCol ); + if ( fabs ( factor ) > SteadyState::EPSILON ) + { + factor = factor / pivot; + for ( size_t j = leftCol + 1; j < U->size2; ++j ) + { + double x = gsl_matrix_get( U, i, j ); + double y = gsl_matrix_get( U, start, j ); + x -= y * factor; + if ( fabs( x ) < SteadyState::EPSILON ) + x = 0.0; + gsl_matrix_set( U, i, j, x ); + } + } + gsl_matrix_set( U, i, leftCol, 0.0 ); // Cleaning up. + } } /** @@ -953,24 +1016,29 @@ void eliminateRowsBelow( gsl_matrix* U, int start, int leftCol ) */ int reorderRows( gsl_matrix* U, int start, int leftCol ) { - int leftMostRow = start; - int numReacs = U->size2 - U->size1; - int newLeftCol = numReacs; - for ( size_t i = start; i < U->size1; ++i ) { - for ( int j = leftCol; j < numReacs; ++j ) { - if ( fabs( gsl_matrix_get( U, i, j ) ) > SteadyState::EPSILON ){ - if ( j < newLeftCol ) { - newLeftCol = j; - leftMostRow = i; - } - break; - } - } - } - if ( leftMostRow != start ) { // swap them. - gsl_matrix_swap_rows( U, start, leftMostRow ); - } - return newLeftCol; + int leftMostRow = start; + int numReacs = U->size2 - U->size1; + int newLeftCol = numReacs; + for ( size_t i = start; i < U->size1; ++i ) + { + for ( int j = leftCol; j < numReacs; ++j ) + { + if ( fabs( gsl_matrix_get( U, i, j ) ) > SteadyState::EPSILON ) + { + if ( j < newLeftCol ) + { + newLeftCol = j; + leftMostRow = i; + } + break; + } + } + } + if ( leftMostRow != start ) // swap them. + { + gsl_matrix_swap_rows( U, start, leftMostRow ); + } + return newLeftCol; } /** @@ -982,19 +1050,20 @@ int reorderRows( gsl_matrix* U, int start, int leftCol ) */ int myGaussianDecomp( gsl_matrix* U ) { - int numMols = U->size1; - int numReacs = U->size2 - numMols; - int i; - // Start out with a nonzero entry at 0,0 - int leftCol = reorderRows( U, 0, 0 ); - - for ( i = 0; i < numMols - 1; ++i ) { - eliminateRowsBelow( U, i, leftCol ); - leftCol = reorderRows( U, i + 1, leftCol ); - if ( leftCol == numReacs ) - break; - } - return i + 1; + int numMols = U->size1; + int numReacs = U->size2 - numMols; + int i; + // Start out with a nonzero entry at 0,0 + int leftCol = reorderRows( U, 0, 0 ); + + for ( i = 0; i < numMols - 1; ++i ) + { + eliminateRowsBelow( U, i, leftCol ); + leftCol = reorderRows( U, i + 1, leftCol ); + if ( leftCol == numReacs ) + break; + } + return i + 1; } ////////////////////////////////////////////////////////////////// @@ -1003,24 +1072,26 @@ int myGaussianDecomp( gsl_matrix* U ) void recalcTotal( vector< double >& tot, gsl_matrix* g, const double* S ) { - assert( g->size1 == tot.size() ); - for ( unsigned int i = 0; i < g->size1; ++i ) { - double t = 0.0; - for ( unsigned int j = 0; j < g->size2; ++j ) - t += gsl_matrix_get( g, i, j ) * S[j]; - tot[ i ] = t; - } + assert( g->size1 == tot.size() ); + for ( unsigned int i = 0; i < g->size1; ++i ) + { + double t = 0.0; + for ( unsigned int j = 0; j < g->size2; ++j ) + t += gsl_matrix_get( g, i, j ) * S[j]; + tot[ i ] = t; + } } #endif // end of long section of functions using GSL static bool checkAboveZero( const vector< double >& y ) { - for ( vector< double >::const_iterator - i = y.begin(); i != y.end(); ++i ) { - if ( *i < 0.0 ) - return false; - } - return true; + for ( vector< double >::const_iterator + i = y.begin(); i != y.end(); ++i ) + { + if ( *i < 0.0 ) + return false; + } + return true; } /** @@ -1030,54 +1101,62 @@ static bool checkAboveZero( const vector< double >& y ) void SteadyState::randomizeInitialCondition( const Eref& me ) { #ifdef USE_GSL - Id ksolve = Field< Id >::get( stoich_, "ksolve" ); - vector< double > nVec = - LookupField< unsigned int, vector< double > >::get( - ksolve,"nVec", 0 ); - int numConsv = total_.size(); - recalcTotal( total_, gamma_, &nVec[0] ); - // The reorderRows function likes to have an I matrix at the end of - // numVarPools_, so we provide space for it, although only its first - // column is used for the total vector. - gsl_matrix* U = gsl_matrix_calloc ( numConsv, numVarPools_ + numConsv ); - for ( int i = 0; i < numConsv; ++i ) { - for ( unsigned int j = 0; j < numVarPools_; ++j ) { - gsl_matrix_set( U, i, j, gsl_matrix_get( gamma_, i, j ) ); - } - gsl_matrix_set( U, i, numVarPools_, total_[i] ); - } - // Do the forward elimination - int rank = myGaussianDecomp( U ); - assert( rank = numConsv ); - - vector< double > eliminatedTotal( numConsv, 0.0 ); - for ( int i = 0; i < numConsv; ++i ) { - eliminatedTotal[i] = gsl_matrix_get( U, i, numVarPools_ ); - } - - // Put Find a vector Y that fits the consv rules. - vector< double > y( numVarPools_, 0.0 ); - do { - fitConservationRules( U, eliminatedTotal, y ); - } while ( !checkAboveZero( y ) ); - - // Sanity check. Try the new vector with the old gamma and tots - for ( int i = 0; i < numConsv; ++i ) { - double tot = 0.0; - for ( unsigned int j = 0; j < numVarPools_; ++j ) { - tot += y[j] * gsl_matrix_get( gamma_, i, j ); - } - assert( fabs( tot - total_[i] ) / tot < EPSILON ); - } - - // Put the new values into S. - // cout << endl; - for ( unsigned int j = 0; j < numVarPools_; ++j ) { - nVec[j] = y[j]; - // cout << y[j] << " "; - } - LookupField< unsigned int, vector< double > >::set( - ksolve,"nVec", 0, nVec ); + Id ksolve = Field< Id >::get( stoich_, "ksolve" ); + vector< double > nVec = + LookupField< unsigned int, vector< double > >::get( + ksolve,"nVec", 0 ); + int numConsv = total_.size(); + recalcTotal( total_, gamma_, &nVec[0] ); + // The reorderRows function likes to have an I matrix at the end of + // numVarPools_, so we provide space for it, although only its first + // column is used for the total vector. + gsl_matrix* U = gsl_matrix_calloc ( numConsv, numVarPools_ + numConsv ); + for ( int i = 0; i < numConsv; ++i ) + { + for ( unsigned int j = 0; j < numVarPools_; ++j ) + { + gsl_matrix_set( U, i, j, gsl_matrix_get( gamma_, i, j ) ); + } + gsl_matrix_set( U, i, numVarPools_, total_[i] ); + } + // Do the forward elimination + int rank = myGaussianDecomp( U ); + assert( rank = numConsv ); + + vector< double > eliminatedTotal( numConsv, 0.0 ); + for ( int i = 0; i < numConsv; ++i ) + { + eliminatedTotal[i] = gsl_matrix_get( U, i, numVarPools_ ); + } + + // Put Find a vector Y that fits the consv rules. + vector< double > y( numVarPools_, 0.0 ); + do + { + fitConservationRules( U, eliminatedTotal, y ); + } + while ( !checkAboveZero( y ) ); + + // Sanity check. Try the new vector with the old gamma and tots + for ( int i = 0; i < numConsv; ++i ) + { + double tot = 0.0; + for ( unsigned int j = 0; j < numVarPools_; ++j ) + { + tot += y[j] * gsl_matrix_get( gamma_, i, j ); + } + assert( fabs( tot - total_[i] ) / tot < EPSILON ); + } + + // Put the new values into S. + // cout << endl; + for ( unsigned int j = 0; j < numVarPools_; ++j ) + { + nVec[j] = y[j]; + // cout << y[j] << " "; + } + LookupField< unsigned int, vector< double > >::set( + ksolve,"nVec", 0, nVec ); #endif } @@ -1087,36 +1166,43 @@ void SteadyState::randomizeInitialCondition( const Eref& me ) */ #ifdef USE_GSL void SteadyState::fitConservationRules( - gsl_matrix* U, const vector< double >& eliminatedTotal, - vector< double >&y - ) + gsl_matrix* U, const vector< double >& eliminatedTotal, + vector< double >&y +) { - int numConsv = total_.size(); - int lastJ = numVarPools_; - for ( int i = numConsv - 1; i >= 0; --i ) { - for ( unsigned int j = 0; j < numVarPools_; ++j ) { - double g = gsl_matrix_get( U, i, j ); - if ( fabs( g ) > EPSILON ) { - // double ytot = calcTot( g, i, j, lastJ ); - double ytot = 0.0; - for ( int k = j; k < lastJ; ++k ) { - y[k] = mtrand(); - ytot += y[k] * gsl_matrix_get( U, i, k ); - } - assert( fabs( ytot ) > EPSILON ); - double lastYtot = 0.0; - for ( unsigned int k = lastJ; k < numVarPools_; ++k ) { - lastYtot += y[k] * gsl_matrix_get( U, i, k ); - } - double scale = ( eliminatedTotal[i] - lastYtot ) / ytot; - for ( int k = j; k < lastJ; ++k ) { - y[k] *= scale; - } - lastJ = j; - break; - } - } - } + int numConsv = total_.size(); + int lastJ = numVarPools_; + for ( int i = numConsv - 1; i >= 0; --i ) + { + for ( unsigned int j = 0; j < numVarPools_; ++j ) + { + double g = gsl_matrix_get( U, i, j ); + if ( fabs( g ) > EPSILON ) + { + // double ytot = calcTot( g, i, j, lastJ ); + double ytot = 0.0; + for ( int k = j; k < lastJ; ++k ) + { + // Use global RNG. + y[k] = moose::mtrand(); + ytot += y[k] * gsl_matrix_get( U, i, k ); + } + assert( fabs( ytot ) > EPSILON ); + double lastYtot = 0.0; + for ( unsigned int k = lastJ; k < numVarPools_; ++k ) + { + lastYtot += y[k] * gsl_matrix_get( U, i, k ); + } + double scale = ( eliminatedTotal[i] - lastYtot ) / ytot; + for ( int k = j; k < lastJ; ++k ) + { + y[k] *= scale; + } + lastJ = j; + break; + } + } + } } #endif diff --git a/moose-core/ksolve/Stoich.cpp b/moose-core/ksolve/Stoich.cpp index 458151401e2c2a0bcb36a9f04671e1e3b3947891..3cd9d9022bc419096a5c75ec90491f2e9a145b13 100644 --- a/moose-core/ksolve/Stoich.cpp +++ b/moose-core/ksolve/Stoich.cpp @@ -81,9 +81,9 @@ const Cinfo* Stoich::initCinfo() " This is used to protect the chemical system from going unstable" " in cases where the numerical integration gives a negative value." " Typically it is a small negative value but is obviously" - " physically impossible. In some cases we want to use the " + " physically impossible. In some cases we want to use the " " solvers to handle general systems of equations (not purely " - " chemical ones), so we have this flag to allow it.", + " chemical ones), so we have this flag to allow it.", &Stoich::setAllowNegative, &Stoich::getAllowNegative ); @@ -554,6 +554,17 @@ vector< unsigned int > Stoich::getPoolIdMap() const return ret; } +Id Stoich::getPoolByIndex( unsigned int index ) const +{ + map< Id, unsigned int >::const_iterator i; + for ( i = poolLookup_.begin(); i != poolLookup_.end(); ++i ) + { + if( i->second == index ) + return i->first; + } + return Id(); +} + unsigned int Stoich::getNumRates() const { return rates_.size(); @@ -594,8 +605,8 @@ const FuncTerm* Stoich::funcs( unsigned int i ) const bool Stoich::isFuncTarget( unsigned int poolIndex ) const { - assert( poolIndex < funcTarget_.size() ); - return ( funcTarget_[poolIndex] != ~0U ); + assert( poolIndex < funcTarget_.size() ); + return ( funcTarget_[poolIndex] != ~0U ); } vector< int > Stoich::getMatrixEntry() const @@ -935,9 +946,9 @@ void Stoich::resizeArrays() species_.resize( totNumPools, 0 ); - funcTarget_.clear(); - // Only the pools controlled by a func (targets) have positive indices. - funcTarget_.resize( totNumPools, ~0 ); + funcTarget_.clear(); + // Only the pools controlled by a func (targets) have positive indices. + funcTarget_.resize( totNumPools, ~0 ); unsigned int totNumRates = ( reacVec_.size() + offSolverReacVec_.size() ) * (1+useOneWay_) + @@ -1089,13 +1100,13 @@ void Stoich::installAndUnschedFunc( Id func, Id pool, double volScale ) string expr = Field< string >::get( func, "expr" ); ft->setExpr( expr ); // Tie the output of the FuncTerm to the pool it controls. - unsigned int targetIndex = convertIdToPoolIndex( pool ); + unsigned int targetIndex = convertIdToPoolIndex( pool ); ft->setTarget( targetIndex ); ft->setVolScale( volScale ); unsigned int funcIndex = convertIdToFuncIndex( func ); assert( funcIndex != ~0U ); - // funcTarget_ vector tracks which pools are controlled by which func. - funcTarget_[targetIndex] = funcIndex; + // funcTarget_ vector tracks which pools are controlled by which func. + funcTarget_[targetIndex] = funcIndex; funcs_[ funcIndex ] = ft; } @@ -1401,8 +1412,9 @@ void Stoich::unZombifyModel() unZombifyPools(); - vector< Id > temp = reacVec_; temp.insert( temp.end(), - offSolverReacVec_.begin(), offSolverReacVec_.end() ); + vector< Id > temp = reacVec_; + temp.insert( temp.end(), + offSolverReacVec_.begin(), offSolverReacVec_.end() ); for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i ) { Element* e = i->element(); @@ -1410,8 +1422,9 @@ void Stoich::unZombifyModel() ReacBase::zombify( e, reacCinfo, Id() ); } - temp = mmEnzVec_; temp.insert( temp.end(), - offSolverMMenzVec_.begin(), offSolverMMenzVec_.end() ); + temp = mmEnzVec_; + temp.insert( temp.end(), + offSolverMMenzVec_.begin(), offSolverMMenzVec_.end() ); for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i ) { Element* e = i->element(); @@ -1419,8 +1432,9 @@ void Stoich::unZombifyModel() EnzBase::zombify( e, mmEnzCinfo, Id() ); } - temp = enzVec_; temp.insert( temp.end(), - offSolverEnzVec_.begin(), offSolverEnzVec_.end() ); + temp = enzVec_; + temp.insert( temp.end(), + offSolverEnzVec_.begin(), offSolverEnzVec_.end() ); for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i ) { Element* e = i->element(); @@ -1428,8 +1442,9 @@ void Stoich::unZombifyModel() CplxEnzBase::zombify( e, enzCinfo, Id() ); } - temp = poolFuncVec_; temp.insert( temp.end(), - incrementFuncVec_.begin(), incrementFuncVec_.end() ); + temp = poolFuncVec_; + temp.insert( temp.end(), + incrementFuncVec_.begin(), incrementFuncVec_.end() ); for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i ) { Element* e = i->element(); diff --git a/moose-core/ksolve/Stoich.h b/moose-core/ksolve/Stoich.h index bea3d067f1b560863ac02f8240841274c1e75af4..93e63b9f79fa7a0b344bb3d85638773206db74d6 100644 --- a/moose-core/ksolve/Stoich.h +++ b/moose-core/ksolve/Stoich.h @@ -91,6 +91,8 @@ class Stoich */ vector< unsigned int > getPoolIdMap() const; + Id getPoolByIndex( unsigned int index ) const; + /** * Take the provided wildcard path to build the list of elements * managed by this solver. @@ -485,7 +487,7 @@ class Stoich */ bool useOneWay_; - /** + /** * True if pools are permitted to take negative concentrations. * This may happen if solver is handling a general equation system * that is not constrained by chemical rules. diff --git a/moose-core/ksolve/VoxelPools.cpp b/moose-core/ksolve/VoxelPools.cpp index 64b07be22f8ab7c16761881de85461b5f606433a..38c5e2e76e3fdba4668df119db07ce2a80127b5a 100644 --- a/moose-core/ksolve/VoxelPools.cpp +++ b/moose-core/ksolve/VoxelPools.cpp @@ -12,7 +12,7 @@ #include <gsl/gsl_errno.h> #include <gsl/gsl_matrix.h> #include <gsl/gsl_odeiv2.h> -#elif USE_BOOST +#elif USE_BOOST_ODE #include <boost/numeric/odeint.hpp> using namespace boost::numeric; #endif @@ -36,17 +36,17 @@ using namespace boost::numeric; VoxelPools::VoxelPools() { #ifdef USE_GSL - driver_ = 0; + driver_ = 0; #endif } VoxelPools::~VoxelPools() { - for ( unsigned int i = 0; i < rates_.size(); ++i ) - delete( rates_[i] ); + for ( unsigned int i = 0; i < rates_.size(); ++i ) + delete( rates_[i] ); #ifdef USE_GSL - if ( driver_ ) - gsl_odeiv2_driver_free( driver_ ); + if ( driver_ ) + gsl_odeiv2_driver_free( driver_ ); #endif } @@ -55,12 +55,12 @@ VoxelPools::~VoxelPools() ////////////////////////////////////////////////////////////// void VoxelPools::reinit( double dt ) { - VoxelPoolsBase::reinit(); + VoxelPoolsBase::reinit(); #ifdef USE_GSL - if ( !driver_ ) - return; - gsl_odeiv2_driver_reset( driver_ ); - gsl_odeiv2_driver_reset_hstart( driver_, dt / 10.0 ); + if ( !driver_ ) + return; + gsl_odeiv2_driver_reset( driver_ ); + gsl_odeiv2_driver_reset_hstart( driver_, dt / 10.0 ); #endif } @@ -68,15 +68,18 @@ void VoxelPools::setStoich( Stoich* s, const OdeSystem* ode ) { stoichPtr_ = s; #ifdef USE_GSL - if ( ode ) { + if ( ode ) + { sys_ = ode->gslSys; if ( driver_ ) gsl_odeiv2_driver_free( driver_ ); + driver_ = gsl_odeiv2_driver_alloc_y_new( - &sys_, ode->gslStep, ode->initStepSize, - ode->epsAbs, ode->epsRel ); + &sys_, ode->gslStep, ode->initStepSize, + ode->epsAbs, ode->epsRel + ); } -#elif USE_BOOST +#elif USE_BOOST_ODE if( ode ) sys_ = ode->boostSys; #endif @@ -88,11 +91,12 @@ void VoxelPools::advance( const ProcInfo* p ) double t = p->currTime - p->dt; #ifdef USE_GSL int status = gsl_odeiv2_driver_apply( driver_, &t, p->currTime, varS()); - if ( status != GSL_SUCCESS ) { + if ( status != GSL_SUCCESS ) + { cout << "Error: VoxelPools::advance: GSL integration error at time " - << t << "\n"; + << t << "\n"; cout << "Error info: " << status << ", " << - gsl_strerror( status ) << endl; + gsl_strerror( status ) << endl; if ( status == GSL_EMAXITER ) cout << "Max number of steps exceeded\n"; else if ( status == GSL_ENOPROG ) @@ -102,7 +106,7 @@ void VoxelPools::advance( const ProcInfo* p ) assert( 0 ); } -#elif USE_BOOST +#elif USE_BOOST_ODE // NOTE: Make sure to assing vp to BoostSys vp. In next call, it will be used by @@ -144,126 +148,128 @@ void VoxelPools::advance( const ProcInfo* p ) if( sys_.method == "rk2" ) odeint::integrate_const( rk_midpoint_stepper_type_() - , sys_ , Svec() - , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) - ); + , sys_ , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); else if( sys_.method == "rk4" ) odeint::integrate_const( rk4_stepper_type_() - , sys_ , Svec() - , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) - ); + , sys_ , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); else if( sys_.method == "rk5") odeint::integrate_const( rk_karp_stepper_type_() - , sys_ , Svec() - , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) - ); + , sys_ , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); else if( sys_.method == "rk5a") odeint::integrate_adaptive( - odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol) - , sys_ - , Svec() - , p->currTime - p->dt - , p->currTime - , p->dt - ); + odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol) + , sys_ + , Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); else if ("rk54" == sys_.method ) odeint::integrate_const( rk_karp_stepper_type_() - , sys_ , Svec() - , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) - ); + , sys_ , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); else if ("rk54a" == sys_.method ) odeint::integrate_adaptive( - odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol ) - , sys_, Svec() - , p->currTime - p->dt - , p->currTime - , p->dt - ); + odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol ) + , sys_, Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); else if ("rk5" == sys_.method ) odeint::integrate_const( rk_dopri_stepper_type_() - , sys_ , Svec() - , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) - ); + , sys_ , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); else if ("rk5a" == sys_.method ) odeint::integrate_adaptive( - odeint::make_controlled<rk_dopri_stepper_type_>( absTol, relTol ) - , sys_, Svec() - , p->currTime - p->dt - , p->currTime - , p->dt - ); + odeint::make_controlled<rk_dopri_stepper_type_>( absTol, relTol ) + , sys_, Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); else if( sys_.method == "rk8" ) odeint::integrate_const( rk_felhberg_stepper_type_() - , sys_ , Svec() - , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) - ); + , sys_ , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); else if( sys_.method == "rk8a" ) odeint::integrate_adaptive( - odeint::make_controlled<rk_felhberg_stepper_type_>( absTol, relTol ) - , sys_, Svec() - , p->currTime - p->dt - , p->currTime - , p->dt - ); + odeint::make_controlled<rk_felhberg_stepper_type_>( absTol, relTol ) + , sys_, Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); else odeint::integrate_adaptive( - odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol ) - , sys_, Svec() - , p->currTime - p->dt - , p->currTime - , p->dt - ); + odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol ) + , sys_, Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); #endif - if ( !stoichPtr_->getAllowNegative() ) { // clean out negatives - unsigned int nv = stoichPtr_->getNumVarPools(); - double* vs = varS(); - for ( unsigned int i = 0; i < nv; ++i ) { - if ( signbit(vs[i]) ) - vs[i] = 0.0; - } - } + if ( !stoichPtr_->getAllowNegative() ) // clean out negatives + { + unsigned int nv = stoichPtr_->getNumVarPools(); + double* vs = varS(); + for ( unsigned int i = 0; i < nv; ++i ) + { + if ( signbit(vs[i]) ) + vs[i] = 0.0; + } + } } void VoxelPools::setInitDt( double dt ) { #ifdef USE_GSL - gsl_odeiv2_driver_reset_hstart( driver_, dt ); + gsl_odeiv2_driver_reset_hstart( driver_, dt ); #endif } #ifdef USE_GSL // static func. This is the function that goes into the Gsl solver. int VoxelPools::gslFunc( double t, const double* y, double *dydt, - void* params ) + void* params ) { - VoxelPools* vp = reinterpret_cast< VoxelPools* >( params ); - // Stoich* s = reinterpret_cast< Stoich* >( params ); - double* q = const_cast< double* >( y ); // Assign the func portion. - - // Assign the buffered pools - // Not possible because this is a static function - // Not needed because dydt = 0; - /* - double* b = q + s->getNumVarPools(); - vector< double >::const_iterator sinit = Sinit_.begin() + s->getNumVarPools(); - for ( unsigned int i = 0; i < s->getNumBufPools(); ++i ) - *b++ = *sinit++; - */ - - vp->stoichPtr_->updateFuncs( q, t ); - vp->updateRates( y, dydt ); + VoxelPools* vp = reinterpret_cast< VoxelPools* >( params ); + // Stoich* s = reinterpret_cast< Stoich* >( params ); + double* q = const_cast< double* >( y ); // Assign the func portion. + + // Assign the buffered pools + // Not possible because this is a static function + // Not needed because dydt = 0; + /* + double* b = q + s->getNumVarPools(); + vector< double >::const_iterator sinit = Sinit_.begin() + s->getNumVarPools(); + for ( unsigned int i = 0; i < s->getNumBufPools(); ++i ) + *b++ = *sinit++; + */ + + vp->stoichPtr_->updateFuncs( q, t ); + vp->updateRates( y, dydt ); #ifdef USE_GSL - return GSL_SUCCESS; + return GSL_SUCCESS; #else - return 0; + return 0; #endif } -#elif USE_BOOST +#elif USE_BOOST_ODE void VoxelPools::evalRates( const vector_type_& y, vector_type_& dydt, const double t, VoxelPools* vp - ) +) { vp->updateRates( &y[0], &dydt[0] ); } @@ -274,64 +280,66 @@ void VoxelPools::evalRates( /////////////////////////////////////////////////////////////////////// void VoxelPools::updateAllRateTerms( const vector< RateTerm* >& rates, - unsigned int numCoreRates ) + unsigned int numCoreRates ) { - // Clear out old rates if any - for ( unsigned int i = 0; i < rates_.size(); ++i ) - delete( rates_[i] ); - - rates_.resize( rates.size() ); - for ( unsigned int i = 0; i < numCoreRates; ++i ) - rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); - for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) { - rates_[i] = rates[i]->copyWithVolScaling( getVolume(), - getXreacScaleSubstrates(i - numCoreRates), - getXreacScaleProducts(i - numCoreRates ) ); - } + // Clear out old rates if any + for ( unsigned int i = 0; i < rates_.size(); ++i ) + delete( rates_[i] ); + + rates_.resize( rates.size() ); + for ( unsigned int i = 0; i < numCoreRates; ++i ) + rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); + for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) + { + rates_[i] = rates[i]->copyWithVolScaling( getVolume(), + getXreacScaleSubstrates(i - numCoreRates), + getXreacScaleProducts(i - numCoreRates ) ); + } } void VoxelPools::updateRateTerms( const vector< RateTerm* >& rates, - unsigned int numCoreRates, unsigned int index ) + unsigned int numCoreRates, unsigned int index ) { - // During setup or expansion of the reac system, it is possible to - // call this function before the rates_ term is assigned. Disable. - if ( index >= rates_.size() ) - return; - delete( rates_[index] ); - if ( index >= numCoreRates ) - rates_[index] = rates[index]->copyWithVolScaling( - getVolume(), - getXreacScaleSubstrates(index - numCoreRates), - getXreacScaleProducts(index - numCoreRates ) ); - else - rates_[index] = rates[index]->copyWithVolScaling( - getVolume(), 1.0, 1.0 ); + // During setup or expansion of the reac system, it is possible to + // call this function before the rates_ term is assigned. Disable. + if ( index >= rates_.size() ) + return; + delete( rates_[index] ); + if ( index >= numCoreRates ) + rates_[index] = rates[index]->copyWithVolScaling( + getVolume(), + getXreacScaleSubstrates(index - numCoreRates), + getXreacScaleProducts(index - numCoreRates ) ); + else + rates_[index] = rates[index]->copyWithVolScaling( + getVolume(), 1.0, 1.0 ); } void VoxelPools::updateRates( const double* s, double* yprime ) const { - const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix(); - vector< double > v( N.nColumns(), 0.0 ); - vector< double >::iterator j = v.begin(); - // totVar should include proxyPools only if this voxel uses them - unsigned int totVar = stoichPtr_->getNumVarPools() + - stoichPtr_->getNumProxyPools(); - // totVar should include proxyPools if this voxel does not use them - unsigned int totInvar = stoichPtr_->getNumBufPools(); - assert( N.nColumns() == 0 || - N.nRows() == stoichPtr_->getNumAllPools() ); - assert( N.nColumns() == rates_.size() ); - - for ( vector< RateTerm* >::const_iterator - i = rates_.begin(); i != rates_.end(); i++) { - *j++ = (**i)( s ); - assert( !std::isnan( *( j-1 ) ) ); - } - - for (unsigned int i = 0; i < totVar; ++i) - *yprime++ = N.computeRowRate( i , v ); - for (unsigned int i = 0; i < totInvar ; ++i) - *yprime++ = 0.0; + const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix(); + vector< double > v( N.nColumns(), 0.0 ); + vector< double >::iterator j = v.begin(); + // totVar should include proxyPools only if this voxel uses them + unsigned int totVar = stoichPtr_->getNumVarPools() + + stoichPtr_->getNumProxyPools(); + // totVar should include proxyPools if this voxel does not use them + unsigned int totInvar = stoichPtr_->getNumBufPools(); + assert( N.nColumns() == 0 || + N.nRows() == stoichPtr_->getNumAllPools() ); + assert( N.nColumns() == rates_.size() ); + + for ( vector< RateTerm* >::const_iterator + i = rates_.begin(); i != rates_.end(); i++) + { + *j++ = (**i)( s ); + assert( !std::isnan( *( j-1 ) ) ); + } + + for (unsigned int i = 0; i < totVar; ++i) + *yprime++ = N.computeRowRate( i , v ); + for (unsigned int i = 0; i < totInvar ; ++i) + *yprime++ = 0.0; } /** @@ -340,28 +348,29 @@ void VoxelPools::updateRates( const double* s, double* yprime ) const * to analyze velocity. */ void VoxelPools::updateReacVelocities( - const double* s, vector< double >& v ) const + const double* s, vector< double >& v ) const { - const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix(); - assert( N.nColumns() == rates_.size() ); - - vector< RateTerm* >::const_iterator i; - v.clear(); - v.resize( rates_.size(), 0.0 ); - vector< double >::iterator j = v.begin(); - - for ( i = rates_.begin(); i != rates_.end(); i++) { - *j++ = (**i)( s ); - assert( !std::isnan( *( j-1 ) ) ); - } + const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix(); + assert( N.nColumns() == rates_.size() ); + + vector< RateTerm* >::const_iterator i; + v.clear(); + v.resize( rates_.size(), 0.0 ); + vector< double >::iterator j = v.begin(); + + for ( i = rates_.begin(); i != rates_.end(); i++) + { + *j++ = (**i)( s ); + assert( !std::isnan( *( j-1 ) ) ); + } } /// For debugging: Print contents of voxel pool void VoxelPools::print() const { - cout << "numAllRates = " << rates_.size() << - ", numLocalRates= " << stoichPtr_->getNumCoreRates() << endl; - VoxelPoolsBase::print(); + cout << "numAllRates = " << rates_.size() << + ", numLocalRates= " << stoichPtr_->getNumCoreRates() << endl; + VoxelPoolsBase::print(); } //////////////////////////////////////////////////////////// @@ -370,8 +379,8 @@ void VoxelPools::print() const */ void VoxelPools::setVolumeAndDependencies( double vol ) { - VoxelPoolsBase::setVolumeAndDependencies( vol ); - updateAllRateTerms( stoichPtr_->getRateTerms(), - stoichPtr_->getNumCoreRates() ); + VoxelPoolsBase::setVolumeAndDependencies( vol ); + updateAllRateTerms( stoichPtr_->getRateTerms(), + stoichPtr_->getNumCoreRates() ); } diff --git a/moose-core/ksolve/VoxelPools.h b/moose-core/ksolve/VoxelPools.h index bd1e5ec5003e23d33699723d04ed21340791458a..a8f0b4aef36a8fe7290eec8418d2716ef684878e 100644 --- a/moose-core/ksolve/VoxelPools.h +++ b/moose-core/ksolve/VoxelPools.h @@ -14,7 +14,7 @@ #include "OdeSystem.h" #include "VoxelPoolsBase.h" -#ifdef USE_BOOST +#ifdef USE_BOOST_ODE #include "BoostSys.h" #endif @@ -52,15 +52,15 @@ public: /// Set initial timestep to use by the solver. void setInitDt( double dt ); -#ifdef USE_GSL /* ----- not USE_BOOST ----- */ +#ifdef USE_GSL /* ----- not USE_BOOST_ODE ----- */ static int gslFunc( double t, const double* y, double *dydt, void* params); -#elif USE_BOOST +#elif USE_BOOST_ODE static void evalRates( const vector_type_& y , vector_type_& dydt , const double t , VoxelPools* vp ); -#endif /* ----- not USE_BOOST ----- */ +#endif /* ----- not USE_BOOST_ODE ----- */ ////////////////////////////////////////////////////////////////// // Rate manipulation and calculation functions @@ -102,7 +102,7 @@ private: #ifdef USE_GSL gsl_odeiv2_driver* driver_; gsl_odeiv2_system sys_; -#elif USE_BOOST +#elif USE_BOOST_ODE BoostSys sys_; #endif diff --git a/moose-core/ksolve/VoxelPoolsBase.cpp b/moose-core/ksolve/VoxelPoolsBase.cpp index 22831c66d816d09784d4dc0cabfc960bf68031e8..f0261245c61cb6ae7f3466519a149d05eba17065 100644 --- a/moose-core/ksolve/VoxelPoolsBase.cpp +++ b/moose-core/ksolve/VoxelPoolsBase.cpp @@ -22,13 +22,14 @@ // Class definitions ////////////////////////////////////////////////////////////// -VoxelPoolsBase::VoxelPoolsBase() - : - stoichPtr_( 0 ), - S_(1), - Sinit_(1), - volume_(1.0) -{ ; } +VoxelPoolsBase::VoxelPoolsBase() : + stoichPtr_( 0 ), + S_(1), + Sinit_(1), + volume_(1.0) +{ + ; +} VoxelPoolsBase::~VoxelPoolsBase() {} @@ -53,91 +54,93 @@ void VoxelPoolsBase::reinit() ////////////////////////////////////////////////////////////// const double* VoxelPoolsBase::S() const { - return &S_[0]; + return &S_[0]; } vector< double >& VoxelPoolsBase::Svec() { - return S_; + return S_; } double* VoxelPoolsBase::varS() { - return &S_[0]; + return &S_[0]; } const double* VoxelPoolsBase::Sinit() const { - return &Sinit_[0]; + return &Sinit_[0]; } double* VoxelPoolsBase::varSinit() { - return &Sinit_[0]; + return &Sinit_[0]; } unsigned int VoxelPoolsBase::size() const { - return Sinit_.size(); + return Sinit_.size(); } void VoxelPoolsBase::setVolume( double vol ) { - volume_ = vol; + volume_ = vol; } double VoxelPoolsBase::getVolume() const { - return volume_; + return volume_; } void VoxelPoolsBase::setVolumeAndDependencies( double vol ) { - double ratio = vol / volume_; - volume_ = vol; - for ( vector< double >::iterator - i = Sinit_.begin(); i != Sinit_.end(); ++i ) - *i *= ratio; + double ratio = vol / volume_; + volume_ = vol; + for ( vector< double >::iterator + i = Sinit_.begin(); i != Sinit_.end(); ++i ) + *i *= ratio; - for ( vector< double >::iterator i = S_.begin(); i != S_.end(); ++i ) - *i *= ratio; + for ( vector< double >::iterator i = S_.begin(); i != S_.end(); ++i ) + *i *= ratio; - // I would like to update the xReacScaleSubstreates and Products here, - // but I don't know the order of their reactions. So leave it to - // a subsequent call via Ksolve or Stoich. + // I would like to update the xReacScaleSubstreates and Products here, + // but I don't know the order of their reactions. So leave it to + // a subsequent call via Ksolve or Stoich. } void VoxelPoolsBase::scaleVolsBufsRates( - double ratio, const Stoich* stoichPtr ) -{ - volume_ *= ratio; // Scale vol - for ( vector< double >::iterator - i = Sinit_.begin(); i != Sinit_.end(); ++i ) - *i *= ratio; // Scale Bufs - // Here we also need to set the Ns for the buffered pools. - unsigned int start = stoichPtr_->getNumVarPools(); - unsigned int end = start + stoichPtr_->getNumBufPools(); - assert( end == Sinit_.size() ); - for ( unsigned int i = start; i < end; ++i ) { - // Must not reassign pools that are controlled by functions. - if ( !stoichPtr->isFuncTarget(i) ) - S_[i] = Sinit_[i]; - } - - // Scale rates. Start by clearing out old rates if any - for ( unsigned int i = 0; i < rates_.size(); ++i ) - delete( rates_[i] ); - - unsigned int numCoreRates = stoichPtr->getNumCoreRates(); - const vector< RateTerm* >& rates = stoichPtr->getRateTerms(); - rates_.resize( rates.size() ); - for ( unsigned int i = 0; i < numCoreRates; ++i ) - rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); - for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) { - rates_[i] = rates[i]->copyWithVolScaling( getVolume(), - getXreacScaleSubstrates(i - numCoreRates), - getXreacScaleProducts(i - numCoreRates ) ); - } + double ratio, const Stoich* stoichPtr ) +{ + volume_ *= ratio; // Scale vol + for ( vector< double >::iterator + i = Sinit_.begin(); i != Sinit_.end(); ++i ) + *i *= ratio; // Scale Bufs + // Here we also need to set the Ns for the buffered pools. + unsigned int start = stoichPtr_->getNumVarPools(); + unsigned int end = start + stoichPtr_->getNumBufPools(); + assert( end == Sinit_.size() ); + for ( unsigned int i = start; i < end; ++i ) + { + // Must not reassign pools that are controlled by functions. + if ( !stoichPtr->isFuncTarget(i) ) + S_[i] = Sinit_[i]; + } + + // Scale rates. Start by clearing out old rates if any + for ( unsigned int i = 0; i < rates_.size(); ++i ) + delete( rates_[i] ); + + unsigned int numCoreRates = stoichPtr->getNumCoreRates(); + const vector< RateTerm* >& rates = stoichPtr->getRateTerms(); + rates_.resize( rates.size() ); + for ( unsigned int i = 0; i < numCoreRates; ++i ) + rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); + for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) + { + rates_[i] = rates[i]->copyWithVolScaling( getVolume(), + getXreacScaleSubstrates(i - numCoreRates), + getXreacScaleProducts(i - numCoreRates ) ); + } } ////////////////////////////////////////////////////////////// @@ -146,129 +149,134 @@ void VoxelPoolsBase::scaleVolsBufsRates( void VoxelPoolsBase::setN( unsigned int i, double v ) { - S_[i] = v; - if ( S_[i] < 0.0 ) - S_[i] = 0.0; + S_[i] = v; + if ( S_[i] < 0.0 ) + S_[i] = 0.0; } double VoxelPoolsBase::getN( unsigned int i ) const { - return S_[i]; + return S_[i]; } void VoxelPoolsBase::setNinit( unsigned int i, double v ) { - Sinit_[i] = v; - if ( Sinit_[i] < 0.0 ) - Sinit_[i] = 0.0; + Sinit_[i] = v; + if ( Sinit_[i] < 0.0 ) + Sinit_[i] = 0.0; } double VoxelPoolsBase::getNinit( unsigned int i ) const { - return Sinit_[i]; + return Sinit_[i]; } void VoxelPoolsBase::setDiffConst( unsigned int i, double v ) { - ; // Do nothing. + ; // Do nothing. } double VoxelPoolsBase::getDiffConst( unsigned int i ) const { - return 0; + return 0; } ////////////////////////////////////////////////////////////// // Handle cross compartment reactions ////////////////////////////////////////////////////////////// void VoxelPoolsBase::xferIn( - const vector< unsigned int >& poolIndex, - const vector< double >& values, - const vector< double >& lastValues, - unsigned int voxelIndex ) + const vector< unsigned int >& poolIndex, + const vector< double >& values, + const vector< double >& lastValues, + unsigned int voxelIndex ) { - unsigned int offset = voxelIndex * poolIndex.size(); - vector< double >::const_iterator i = values.begin() + offset; - vector< double >::const_iterator j = lastValues.begin() + offset; - for ( vector< unsigned int >::const_iterator - k = poolIndex.begin(); k != poolIndex.end(); ++k ) { - S_[*k] += *i++ - *j++; - } + unsigned int offset = voxelIndex * poolIndex.size(); + vector< double >::const_iterator i = values.begin() + offset; + vector< double >::const_iterator j = lastValues.begin() + offset; + for ( vector< unsigned int >::const_iterator + k = poolIndex.begin(); k != poolIndex.end(); ++k ) + { + S_[*k] += *i++ - *j++; + } } void VoxelPoolsBase::xferInOnlyProxies( - const vector< unsigned int >& poolIndex, - const vector< double >& values, - unsigned int numProxyPools, - unsigned int voxelIndex ) -{ - unsigned int offset = voxelIndex * poolIndex.size(); - vector< double >::const_iterator i = values.begin() + offset; - unsigned int proxyEndIndex = stoichPtr_->getNumVarPools() + - stoichPtr_->getNumProxyPools(); - for ( vector< unsigned int >::const_iterator - k = poolIndex.begin(); k != poolIndex.end(); ++k ) { - // if ( *k >= S_.size() - numProxyPools ) - if ( *k >= stoichPtr_->getNumVarPools() && *k < proxyEndIndex ) { - // cout << S_[*k] << ", " << Sinit_[*k] << ", " << *i << endl; - Sinit_[*k] = *i; - S_[*k] = *i; - } - i++; - } + const vector< unsigned int >& poolIndex, + const vector< double >& values, + unsigned int numProxyPools, + unsigned int voxelIndex ) +{ + unsigned int offset = voxelIndex * poolIndex.size(); + vector< double >::const_iterator i = values.begin() + offset; + unsigned int proxyEndIndex = stoichPtr_->getNumVarPools() + + stoichPtr_->getNumProxyPools(); + for ( vector< unsigned int >::const_iterator + k = poolIndex.begin(); k != poolIndex.end(); ++k ) + { + // if ( *k >= S_.size() - numProxyPools ) + if ( *k >= stoichPtr_->getNumVarPools() && *k < proxyEndIndex ) + { + // cout << S_[*k] << ", " << Sinit_[*k] << ", " << *i << endl; + Sinit_[*k] = *i; + S_[*k] = *i; + } + i++; + } } void VoxelPoolsBase::xferOut( - unsigned int voxelIndex, - vector< double >& values, - const vector< unsigned int >& poolIndex) + unsigned int voxelIndex, + vector< double >& values, + const vector< unsigned int >& poolIndex) { - unsigned int offset = voxelIndex * poolIndex.size(); - vector< double >::iterator i = values.begin() + offset; - for ( vector< unsigned int >::const_iterator - k = poolIndex.begin(); k != poolIndex.end(); ++k ) { - *i++ = S_[*k]; - } + unsigned int offset = voxelIndex * poolIndex.size(); + vector< double >::iterator i = values.begin() + offset; + for ( vector< unsigned int >::const_iterator + k = poolIndex.begin(); k != poolIndex.end(); ++k ) + { + *i++ = S_[*k]; + } } void VoxelPoolsBase::addProxyVoxy( - unsigned int comptIndex, Id otherComptId, unsigned int voxel ) + unsigned int comptIndex, Id otherComptId, unsigned int voxel ) { - if ( comptIndex >= proxyPoolVoxels_.size() ) { - proxyPoolVoxels_.resize( comptIndex + 1 ); - } + if ( comptIndex >= proxyPoolVoxels_.size() ) + { + proxyPoolVoxels_.resize( comptIndex + 1 ); + } - proxyPoolVoxels_[comptIndex].push_back( voxel ); - proxyComptMap_[otherComptId] = comptIndex; + proxyPoolVoxels_[comptIndex].push_back( voxel ); + proxyComptMap_[otherComptId] = comptIndex; } void VoxelPoolsBase::addProxyTransferIndex( - unsigned int comptIndex, unsigned int transferIndex ) + unsigned int comptIndex, unsigned int transferIndex ) { - if ( comptIndex >= proxyTransferIndex_.size() ) - proxyTransferIndex_.resize( comptIndex + 1 ); - proxyTransferIndex_[comptIndex].push_back( transferIndex ); + if ( comptIndex >= proxyTransferIndex_.size() ) + proxyTransferIndex_.resize( comptIndex + 1 ); + proxyTransferIndex_[comptIndex].push_back( transferIndex ); } bool VoxelPoolsBase::hasXfer( unsigned int comptIndex ) const { - if ( comptIndex >= proxyPoolVoxels_.size() ) - return false; - return (proxyPoolVoxels_[ comptIndex ].size() > 0); + if ( comptIndex >= proxyPoolVoxels_.size() ) + return false; + return (proxyPoolVoxels_[ comptIndex ].size() > 0); } bool VoxelPoolsBase::isVoxelJunctionPresent( Id i1, Id i2 ) const { - if ( i1 == Id () ) - return false; - if ( proxyComptMap_.find( i1 ) == proxyComptMap_.end() ) - return false; - if ( i2 == Id() ) // This is intentionally blank, only one jn. - return true; - // If there is an i2 but it isn't on the map, then not connected. - if ( proxyComptMap_.find( i2 ) == proxyComptMap_.end() ) - return false; - return true; + if ( i1 == Id () ) + return false; + if ( proxyComptMap_.find( i1 ) == proxyComptMap_.end() ) + return false; + if ( i2 == Id() ) // This is intentionally blank, only one jn. + return true; + // If there is an i2 but it isn't on the map, then not connected. + if ( proxyComptMap_.find( i2 ) == proxyComptMap_.end() ) + return false; + return true; } //////////////////////////////////////////////////////////////////// @@ -277,32 +285,32 @@ bool VoxelPoolsBase::isVoxelJunctionPresent( Id i1, Id i2 ) const void VoxelPoolsBase::resetXreacScale( unsigned int size ) { - xReacScaleSubstrates_.assign( size, 1.0 ); - xReacScaleProducts_.assign( size, 1.0 ); + xReacScaleSubstrates_.assign( size, 1.0 ); + xReacScaleProducts_.assign( size, 1.0 ); } void VoxelPoolsBase::forwardReacVolumeFactor( unsigned int i, double volume ) { - assert( i < xReacScaleSubstrates_.size() ); - xReacScaleSubstrates_[i] *= volume / getVolume(); - // cout << "forwardReacVolumeFactor[" << i << "] = " << xReacScaleSubstrates_[i] <<endl; + assert( i < xReacScaleSubstrates_.size() ); + xReacScaleSubstrates_[i] *= volume / getVolume(); + // cout << "forwardReacVolumeFactor[" << i << "] = " << xReacScaleSubstrates_[i] <<endl; } void VoxelPoolsBase::backwardReacVolumeFactor( unsigned int i, double volume ) { - assert( i < xReacScaleProducts_.size() ); - xReacScaleProducts_[i] *= volume / getVolume(); - // cout << "backwardReacVolumeFactor[" << i << "] = "<< xReacScaleProducts_[i] <<endl; + assert( i < xReacScaleProducts_.size() ); + xReacScaleProducts_[i] *= volume / getVolume(); + // cout << "backwardReacVolumeFactor[" << i << "] = "<< xReacScaleProducts_[i] <<endl; } double VoxelPoolsBase::getXreacScaleSubstrates( unsigned int i ) const { - return xReacScaleSubstrates_[i]; + return xReacScaleSubstrates_[i]; } double VoxelPoolsBase::getXreacScaleProducts( unsigned int i ) const { - return xReacScaleProducts_[i]; + return xReacScaleProducts_[i]; } /** @@ -310,88 +318,102 @@ double VoxelPoolsBase::getXreacScaleProducts( unsigned int i ) const * are not present on current voxel. */ void VoxelPoolsBase::filterCrossRateTerms( - const vector< Id >& offSolverReacs, - const vector< pair< Id, Id > >& offSolverReacCompts ) -{ - assert (offSolverReacs.size() == offSolverReacCompts.size() ); - // unsigned int numCoreRates = stoichPtr_->getNumCoreRates(); - for ( unsigned int i = 0; i < offSolverReacCompts.size(); ++i ) { - const pair< Id, Id >& p = offSolverReacCompts[i]; - if ( !isVoxelJunctionPresent( p.first, p.second) ) { - Id reacId = offSolverReacs[i]; - const Cinfo* reacCinfo = reacId.element()->cinfo(); - unsigned int k = stoichPtr_->convertIdToReacIndex( offSolverReacs[i] ); - // Start by replacing the immediate cross reaction term. - if ( rates_[k] ) - delete rates_[k]; - rates_[k] = new ExternReac; - if ( stoichPtr_->getOneWay() ) { - k++; // Delete the next entry too, it is the reverse reacn. - assert( k < rates_.size() ); - if ( reacCinfo->isA( "ReacBase" ) ) { - if ( rates_[k] ) - delete rates_[k]; - rates_[k] = new ExternReac; - } - if ( reacCinfo->isA( "CplxEnzBase" ) ) { // Delete next two. - if ( rates_[k] ) - delete rates_[k]; - rates_[k] = new ExternReac; - k++; - assert( k < rates_.size() ); - if ( rates_[k] ) - delete rates_[k]; - rates_[k] = new ExternReac; - } - } else { - if ( reacCinfo->isA( "CplxEnzBase" ) ) { // Delete next one. - k++; - assert( k < rates_.size() ); - if ( rates_[k] ) - delete rates_[k]; - rates_[k] = new ExternReac; - } - } - } - } + const vector< Id >& offSolverReacs, + const vector< pair< Id, Id > >& offSolverReacCompts ) +{ + assert (offSolverReacs.size() == offSolverReacCompts.size() ); + // unsigned int numCoreRates = stoichPtr_->getNumCoreRates(); + for ( unsigned int i = 0; i < offSolverReacCompts.size(); ++i ) + { + const pair< Id, Id >& p = offSolverReacCompts[i]; + if ( !isVoxelJunctionPresent( p.first, p.second) ) + { + Id reacId = offSolverReacs[i]; + const Cinfo* reacCinfo = reacId.element()->cinfo(); + unsigned int k = stoichPtr_->convertIdToReacIndex( offSolverReacs[i] ); + // Start by replacing the immediate cross reaction term. + if ( rates_[k] ) + delete rates_[k]; + rates_[k] = new ExternReac; + if ( stoichPtr_->getOneWay() ) + { + k++; // Delete the next entry too, it is the reverse reacn. + assert( k < rates_.size() ); + if ( reacCinfo->isA( "ReacBase" ) ) + { + if ( rates_[k] ) + delete rates_[k]; + rates_[k] = new ExternReac; + } + if ( reacCinfo->isA( "CplxEnzBase" ) ) // Delete next two. + { + if ( rates_[k] ) + delete rates_[k]; + rates_[k] = new ExternReac; + k++; + assert( k < rates_.size() ); + if ( rates_[k] ) + delete rates_[k]; + rates_[k] = new ExternReac; + } + } + else + { + if ( reacCinfo->isA( "CplxEnzBase" ) ) // Delete next one. + { + k++; + assert( k < rates_.size() ); + if ( rates_[k] ) + delete rates_[k]; + rates_[k] = new ExternReac; + } + } + } + } } //////////////////////////////////////////////////////////////////////// void VoxelPoolsBase::print() const { - cout << "S_.size=" << S_.size() << ", volume = " << volume_ << endl; - cout << "proxyPoolsVoxels.size()=" << proxyPoolVoxels_.size() << - ", proxyTransferIndex.size()=" << proxyTransferIndex_.size() << - endl; - assert( proxyPoolVoxels_.size() == proxyTransferIndex_.size() ); - for ( unsigned int i = 0; i < proxyPoolVoxels_.size(); ++i ) { - cout << "ppv[" << i << "]="; - const vector< unsigned int >& ppv = proxyPoolVoxels_[i]; - for ( unsigned int j = 0; j < ppv.size(); ++j ) { - cout << " " << ppv[j]; - } - cout << endl; - } - for ( unsigned int i = 0; i < proxyTransferIndex_.size(); ++i ) { - cout << "pti[" << i << "]="; - const vector< unsigned int >& pti = proxyTransferIndex_[i]; - for ( unsigned int j = 0; j < pti.size(); ++j ) { - cout << " " << pti[j]; - } - cout << endl; - } - cout << - "xReacScaleSubstrates.size()=" << xReacScaleSubstrates_.size() << - ", xReacScaleProducts.size()=" << xReacScaleProducts_.size() << - endl; - assert( xReacScaleSubstrates_.size() == xReacScaleProducts_.size() ); - for ( unsigned int i = 0; i < xReacScaleSubstrates_.size(); ++i ) { - cout << i << " " << xReacScaleSubstrates_[i] << " " << - xReacScaleProducts_[i] << endl; - } - cout << "############## RATES ######################\n"; - for ( unsigned int i = 0; i < rates_.size(); ++i ) { - cout << i << " : " << rates_[i]->getR1() << ", " << - rates_[i]->getR2() << endl; - } + cout << "S_.size=" << S_.size() << ", volume = " << volume_ << endl; + cout << "proxyPoolsVoxels.size()=" << proxyPoolVoxels_.size() << + ", proxyTransferIndex.size()=" << proxyTransferIndex_.size() << + endl; + assert( proxyPoolVoxels_.size() == proxyTransferIndex_.size() ); + for ( unsigned int i = 0; i < proxyPoolVoxels_.size(); ++i ) + { + cout << "ppv[" << i << "]="; + const vector< unsigned int >& ppv = proxyPoolVoxels_[i]; + for ( unsigned int j = 0; j < ppv.size(); ++j ) + { + cout << " " << ppv[j]; + } + cout << endl; + } + for ( unsigned int i = 0; i < proxyTransferIndex_.size(); ++i ) + { + cout << "pti[" << i << "]="; + const vector< unsigned int >& pti = proxyTransferIndex_[i]; + for ( unsigned int j = 0; j < pti.size(); ++j ) + { + cout << " " << pti[j]; + } + cout << endl; + } + cout << + "xReacScaleSubstrates.size()=" << xReacScaleSubstrates_.size() << + ", xReacScaleProducts.size()=" << xReacScaleProducts_.size() << + endl; + assert( xReacScaleSubstrates_.size() == xReacScaleProducts_.size() ); + for ( unsigned int i = 0; i < xReacScaleSubstrates_.size(); ++i ) + { + cout << i << " " << xReacScaleSubstrates_[i] << " " << + xReacScaleProducts_[i] << endl; + } + cout << "############## RATES ######################\n"; + for ( unsigned int i = 0; i < rates_.size(); ++i ) + { + cout << i << " : " << rates_[i]->getR1() << ", " << + rates_[i]->getR2() << endl; + } } diff --git a/moose-core/mesh/NeuroNode.cpp b/moose-core/mesh/NeuroNode.cpp index 9e86634acaf067e232023a23daba1e53f2035476..9610227b2308ada7650fd9cb00e2ad9853b4cf50 100644 --- a/moose-core/mesh/NeuroNode.cpp +++ b/moose-core/mesh/NeuroNode.cpp @@ -533,6 +533,8 @@ void NeuroNode::buildSpinyTree( void NeuroNode::setParentAndChildren( unsigned int index, int dendParent, vector< NeuroNode >& nodes, const unordered_map< Id, unsigned int >& dendMap ) { + if (dendParent < 0 || static_cast< unsigned int >(dendParent) >= nodes.size() ) + return; parent_ = dendParent; const unordered_map< Id, unsigned int >::const_iterator dendLookup = dendMap.find( nodes[dendParent].elecCompt_ ); diff --git a/moose-core/msg/SingleMsg.cpp b/moose-core/msg/SingleMsg.cpp index 8286e2e75414928e73192aed52c4bb328e4eab9c..c8ba6f001d952beb817fbf2e019e1b5f6230d2d8 100644 --- a/moose-core/msg/SingleMsg.cpp +++ b/moose-core/msg/SingleMsg.cpp @@ -19,48 +19,51 @@ vector< SingleMsg* > SingleMsg::msg_; ///////////////////////////////////////////////////////////////////// SingleMsg::SingleMsg( const Eref& e1, const Eref& e2, unsigned int msgIndex) - : Msg( ObjId( managerId_, (msgIndex != 0 ) ? msgIndex: msg_.size() ), - e1.element(), e2.element() ), - i1_( e1.dataIndex() ), - i2_( e2.dataIndex() ), - f2_( e2.fieldIndex() ) -{ - if ( msgIndex == 0 ) { - msg_.push_back( this ); - return; - } else if ( msg_.size() <= msgIndex ) { - msg_.resize( msgIndex + 1 ); - } - msg_[ msgIndex ] = this; + : Msg( ObjId( managerId_, (msgIndex != 0 ) ? msgIndex: msg_.size() ), + e1.element(), e2.element() ), + i1_( e1.dataIndex() ), + i2_( e2.dataIndex() ), + f2_( e2.fieldIndex() ) +{ + if ( msgIndex == 0 ) + { + msg_.push_back( this ); + return; + } + else if ( msg_.size() <= msgIndex ) + { + msg_.resize( msgIndex + 1 ); + } + msg_[ msgIndex ] = this; } SingleMsg::~SingleMsg() { - assert( mid_.dataIndex < msg_.size() ); - msg_[ mid_.dataIndex ] = 0; // ensure deleted ptr isn't reused. + assert( mid_.dataIndex < msg_.size() ); + msg_[ mid_.dataIndex ] = 0; // ensure deleted ptr isn't reused. } Eref SingleMsg::firstTgt( const Eref& src ) const { - if ( src.element() == e1_ ) - return Eref( e2_, i2_, f2_ ); - else if ( src.element() == e2_ ) - return Eref( e1_, i1_ ); - return Eref( 0, 0 ); + if ( src.element() == e1_ ) + return Eref( e2_, i2_, f2_ ); + else if ( src.element() == e2_ ) + return Eref( e1_, i1_ ); + return Eref( 0, 0 ); } void SingleMsg::sources( vector< vector< Eref > >& v ) const { - v.clear(); - v.resize( e2_->numData() ); - v[i2_].resize( 1, Eref( e1_, i1_ ) ); + v.clear(); + v.resize( e2_->numData() ); + v[i2_].resize( 1, Eref( e1_, i1_ ) ); } void SingleMsg::targets( vector< vector< Eref > >& v ) const { - v.clear(); - v.resize( e1_->numData() ); - v[i1_].resize( 1, Eref( e2_, i2_, f2_ ) ); + v.clear(); + v.resize( e1_->numData() ); + v[i1_].resize( 1, Eref( e2_, i2_, f2_ ) ); } @@ -77,54 +80,65 @@ bool SingleMsg::isMsgHere( const Qinfo& q ) const DataId SingleMsg::i1() const { - return i1_; + return i1_; } DataId SingleMsg::i2() const { - return i2_; + return i2_; } Id SingleMsg::managerId() const { - return SingleMsg::managerId_; + return SingleMsg::managerId_; } ObjId SingleMsg::findOtherEnd( ObjId f ) const { - if ( f.element() == e1() ) { - if ( f.dataIndex == i1_ ) - return ObjId( e2()->id(), i2_ ); - } else if ( f.element() == e2() ) { - if ( f.dataIndex == i2_ ) - return ObjId( e1()->id(), i1_ ); - } - return ObjId( 0, BADINDEX ); + if ( f.element() == e1() ) + { + if ( f.dataIndex == i1_ ) + return ObjId( e2()->id(), i2_ ); + } + else if ( f.element() == e2() ) + { + if ( f.dataIndex == i2_ ) + return ObjId( e1()->id(), i1_ ); + } + return ObjId( 0, BADINDEX ); } Msg* SingleMsg::copy( Id origSrc, Id newSrc, Id newTgt, - FuncId fid, unsigned int b, unsigned int n ) const -{ - const Element* orig = origSrc.element(); - if ( n <= 1 ) { - SingleMsg* ret = 0; - if ( orig == e1() ) { - ret = new SingleMsg( Eref( newSrc.element(), i1_ ), - Eref( newTgt.element(), i2_, f2_ ), 0 ); - ret->e1()->addMsgAndFunc( ret->mid(), fid, b ); - } else if ( orig == e2() ) { - ret = new SingleMsg( Eref( newTgt.element(), i1_ ), - Eref( newSrc.element(), i2_, f2_ ), 0 ); - ret->e2()->addMsgAndFunc( ret->mid(), fid, b ); - } else { - assert( 0 ); - } - return ret; - } else { - // Here we need a SliceMsg which goes from one 2-d array to another. - cout << "Error: SingleMsg::copy: SliceMsg not yet implemented\n"; - return 0; - } + FuncId fid, unsigned int b, unsigned int n ) const +{ + const Element* orig = origSrc.element(); + if ( n <= 1 ) + { + SingleMsg* ret = 0; + if ( orig == e1() ) + { + ret = new SingleMsg( Eref( newSrc.element(), i1_ ), + Eref( newTgt.element(), i2_, f2_ ), 0 ); + ret->e1()->addMsgAndFunc( ret->mid(), fid, b ); + } + else if ( orig == e2() ) + { + ret = new SingleMsg( Eref( newTgt.element(), i1_ ), + Eref( newSrc.element(), i2_, f2_ ), 0 ); + ret->e2()->addMsgAndFunc( ret->mid(), fid, b ); + } + else + { + assert( 0 ); + } + return ret; + } + else + { + // Here we need a SliceMsg which goes from one 2-d array to another. + cout << "Error: SingleMsg::copy: SliceMsg not yet implemented\n"; + return 0; + } } /////////////////////////////////////////////////////////////////////// @@ -133,37 +147,38 @@ Msg* SingleMsg::copy( Id origSrc, Id newSrc, Id newTgt, const Cinfo* SingleMsg::initCinfo() { - /////////////////////////////////////////////////////////////////// - // Field definitions. - /////////////////////////////////////////////////////////////////// - static ValueFinfo< SingleMsg, DataId > index1( - "i1", - "Index of source object.", - &SingleMsg::setI1, - &SingleMsg::getI1 - ); - static ValueFinfo< SingleMsg, DataId > index2( - "i2", - "Index of dest object.", - &SingleMsg::setI2, - &SingleMsg::getI2 - ); - - static Finfo* singleMsgFinfos[] = { - &index1, // value - &index2, // value - }; - - static Dinfo< short > dinfo; - static Cinfo singleMsgCinfo ( - "SingleMsg", // name - Msg::initCinfo(), // base class - singleMsgFinfos, - sizeof( singleMsgFinfos ) / sizeof( Finfo* ), // num Fields - &dinfo - ); - - return &singleMsgCinfo; + /////////////////////////////////////////////////////////////////// + // Field definitions. + /////////////////////////////////////////////////////////////////// + static ValueFinfo< SingleMsg, DataId > index1( + "i1", + "Index of source object.", + &SingleMsg::setI1, + &SingleMsg::getI1 + ); + static ValueFinfo< SingleMsg, DataId > index2( + "i2", + "Index of dest object.", + &SingleMsg::setI2, + &SingleMsg::getI2 + ); + + static Finfo* singleMsgFinfos[] = + { + &index1, // value + &index2, // value + }; + + static Dinfo< short > dinfo; + static Cinfo singleMsgCinfo ( + "SingleMsg", // name + Msg::initCinfo(), // base class + singleMsgFinfos, + sizeof( singleMsgFinfos ) / sizeof( Finfo* ), // num Fields + &dinfo + ); + + return &singleMsgCinfo; } static const Cinfo* singleMsgCinfo = SingleMsg::initCinfo(); @@ -171,48 +186,48 @@ static const Cinfo* singleMsgCinfo = SingleMsg::initCinfo(); DataId SingleMsg::getI1() const { - return i1_; + return i1_; } void SingleMsg::setI1( DataId di ) { - i1_ = di; - e1()->markRewired(); - e2()->markRewired(); + i1_ = di; + e1()->markRewired(); + e2()->markRewired(); } DataId SingleMsg::getI2() const { - return i2_; + return i2_; } void SingleMsg::setI2( DataId di ) { - i2_ = di; - e1()->markRewired(); - e2()->markRewired(); + i2_ = di; + e1()->markRewired(); + e2()->markRewired(); } void SingleMsg::setTargetField( unsigned int f ) { - f2_ = f; - e1()->markRewired(); + f2_ = f; + e1()->markRewired(); } unsigned int SingleMsg::getTargetField() const { - return f2_; + return f2_; } /// Static function for Msg access unsigned int SingleMsg::numMsg() { - return msg_.size(); + return msg_.size(); } /// Static function for Msg access char* SingleMsg::lookupMsg( unsigned int index ) { - assert( index < msg_.size() ); - return reinterpret_cast< char* >( msg_[index] ); + assert( index < msg_.size() ); + return reinterpret_cast< char* >( msg_[index] ); } diff --git a/moose-core/msg/SparseMsg.cpp b/moose-core/msg/SparseMsg.cpp index 7511aa0f50a3bd437011e33bf60d66576d7e974b..0196ed30df92d83c61b7802f9615d1e557583778 100644 --- a/moose-core/msg/SparseMsg.cpp +++ b/moose-core/msg/SparseMsg.cpp @@ -7,11 +7,11 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include "header.h" -#include "SparseMatrix.h" -#include "SparseMsg.h" -#include "../randnum/randnum.h" +#include "../basecode/header.h" +#include "../basecode/global.h" #include "../shell/Shell.h" +#include "../basecode/SparseMatrix.h" +#include "SparseMsg.h" // Initializing static variables Id SparseMsg::managerId_; @@ -23,34 +23,34 @@ vector< SparseMsg* > SparseMsg::msg_; const Cinfo* SparseMsg::initCinfo() { - /////////////////////////////////////////////////////////////////// - // Field definitions. - /////////////////////////////////////////////////////////////////// - static ReadOnlyValueFinfo< SparseMsg, unsigned int > numRows( - "numRows", - "Number of rows in matrix.", - &SparseMsg::getNumRows - ); - static ReadOnlyValueFinfo< SparseMsg, unsigned int > numColumns( - "numColumns", - "Number of columns in matrix.", - &SparseMsg::getNumColumns - ); - static ReadOnlyValueFinfo< SparseMsg, unsigned int > numEntries( - "numEntries", - "Number of Entries in matrix.", - &SparseMsg::getNumEntries - ); - - static ValueFinfo< SparseMsg, vector< unsigned int > > connectionList( - "connectionList", - "Pairwise specification of connection matrix where each x,y value " - "represents a connection from src[x] to dest[y]. " - "The (x,y) entries are ordered in a single vector as \n" - "(x0, x1,... x_n-1, y0, y1,... y_n-1)\n", - &SparseMsg::setEntryPairs, - &SparseMsg::getEntryPairs - ); + /////////////////////////////////////////////////////////////////// + // Field definitions. + /////////////////////////////////////////////////////////////////// + static ReadOnlyValueFinfo< SparseMsg, unsigned int > numRows( + "numRows", + "Number of rows in matrix.", + &SparseMsg::getNumRows + ); + static ReadOnlyValueFinfo< SparseMsg, unsigned int > numColumns( + "numColumns", + "Number of columns in matrix.", + &SparseMsg::getNumColumns + ); + static ReadOnlyValueFinfo< SparseMsg, unsigned int > numEntries( + "numEntries", + "Number of Entries in matrix.", + &SparseMsg::getNumEntries + ); + + static ValueFinfo< SparseMsg, vector< unsigned int > > connectionList( + "connectionList", + "Pairwise specification of connection matrix where each x,y value " + "represents a connection from src[x] to dest[y]. " + "The (x,y) entries are ordered in a single vector as \n" + "(x0, x1,... x_n-1, y0, y1,... y_n-1)\n", + &SparseMsg::setEntryPairs, + &SparseMsg::getEntryPairs + ); /// Connection matrix entries to manipulate in Python. static ReadOnlyValueFinfo< SparseMsg, vector< unsigned int > > @@ -76,106 +76,107 @@ const Cinfo* SparseMsg::initCinfo() &SparseMsg::getRowStart ); - static ValueFinfo< SparseMsg, double > probability( - "probability", - "connection probability for random connectivity.", - &SparseMsg::setProbability, - &SparseMsg::getProbability - ); + static ValueFinfo< SparseMsg, double > probability( + "probability", + "connection probability for random connectivity.", + &SparseMsg::setProbability, + &SparseMsg::getProbability + ); - static ValueFinfo< SparseMsg, long > seed( - "seed", - "Random number seed for generating probabilistic connectivity.", - &SparseMsg::setSeed, - &SparseMsg::getSeed - ); + static ValueFinfo< SparseMsg, unsigned long > seed( + "seed", + "Random number seed for generating probabilistic connectivity.", + &SparseMsg::setSeed, + &SparseMsg::getSeed + ); //////////////////////////////////////////////////////////////////////// // DestFinfos //////////////////////////////////////////////////////////////////////// - static DestFinfo setRandomConnectivity( "setRandomConnectivity", - "Assigns connectivity with specified probability and seed", - new OpFunc2< SparseMsg, double, long >( - &SparseMsg::setRandomConnectivity ) ); - - static DestFinfo setEntry( "setEntry", - "Assigns single row,column value", - new OpFunc3< SparseMsg, unsigned int, unsigned int, unsigned int >( - &SparseMsg::setEntry ) ); - - static DestFinfo unsetEntry( "unsetEntry", - "Clears single row,column entry", - new OpFunc2< SparseMsg, unsigned int, unsigned int >( - &SparseMsg::unsetEntry ) ); - - static DestFinfo clear( "clear", - "Clears out the entire matrix", - new OpFunc0< SparseMsg >( - &SparseMsg::clear ) ); - - static DestFinfo transpose( "transpose", - "Transposes the sparse matrix", - new OpFunc0< SparseMsg >( - &SparseMsg::transpose ) ); - - static DestFinfo pairFill( "pairFill", - "Fills entire matrix using pairs of (x,y) indices to indicate " - "presence of a connection. If the target is a FieldElement it" - "automagically assigns FieldIndices.", - new OpFunc2< SparseMsg, - vector< unsigned int >, vector< unsigned int> >( - &SparseMsg::pairFill ) ); - - static DestFinfo tripletFill( "tripletFill", - "Fills entire matrix using triplets of (x,y,fieldIndex) to fully " - "specify every connection in the sparse matrix.", - new OpFunc3< SparseMsg, - vector< unsigned int >, vector< unsigned int>, - vector< unsigned int > >( - &SparseMsg::tripletFill ) ); - - static DestFinfo tripletFill1( "tripletFill1", - "Single contiguous array to fill entire connection matrix using " - "triplets of (x,y, fieldindex) ordered as \n" - "(x0, x1,... xn-1, y0, y1,... yn-1, fi0, fi1,... fi_n-1)\n", - new OpFunc1< SparseMsg, vector< unsigned int > >( - &SparseMsg::tripletFill1 ) ); + static DestFinfo setRandomConnectivity( "setRandomConnectivity", + "Assigns connectivity with specified probability and seed", + new OpFunc2< SparseMsg, double, long >( + &SparseMsg::setRandomConnectivity ) ); + + static DestFinfo setEntry( "setEntry", + "Assigns single row,column value", + new OpFunc3< SparseMsg, unsigned int, unsigned int, unsigned int >( + &SparseMsg::setEntry ) ); + + static DestFinfo unsetEntry( "unsetEntry", + "Clears single row,column entry", + new OpFunc2< SparseMsg, unsigned int, unsigned int >( + &SparseMsg::unsetEntry ) ); + + static DestFinfo clear( "clear", + "Clears out the entire matrix", + new OpFunc0< SparseMsg >( + &SparseMsg::clear ) ); + + static DestFinfo transpose( "transpose", + "Transposes the sparse matrix", + new OpFunc0< SparseMsg >( + &SparseMsg::transpose ) ); + + static DestFinfo pairFill( "pairFill", + "Fills entire matrix using pairs of (x,y) indices to indicate " + "presence of a connection. If the target is a FieldElement it" + "automagically assigns FieldIndices.", + new OpFunc2< SparseMsg, + vector< unsigned int >, vector< unsigned int> >( + &SparseMsg::pairFill ) ); + + static DestFinfo tripletFill( "tripletFill", + "Fills entire matrix using triplets of (x,y,fieldIndex) to fully " + "specify every connection in the sparse matrix.", + new OpFunc3< SparseMsg, + vector< unsigned int >, vector< unsigned int>, + vector< unsigned int > >( + &SparseMsg::tripletFill ) ); + + static DestFinfo tripletFill1( "tripletFill1", + "Single contiguous array to fill entire connection matrix using " + "triplets of (x,y, fieldindex) ordered as \n" + "(x0, x1,... xn-1, y0, y1,... yn-1, fi0, fi1,... fi_n-1)\n", + new OpFunc1< SparseMsg, vector< unsigned int > >( + &SparseMsg::tripletFill1 ) ); //////////////////////////////////////////////////////////////////////// // Assemble it all. //////////////////////////////////////////////////////////////////////// - static Finfo* sparseMsgFinfos[] = { - &numRows, // readonly value - &numColumns, // readonly value - &numEntries, // readonly value - &connectionList, // value - &matrixEntry, // ReadOnlyValue - &columnIndex, // ReadOnlyValue - &rowStart, // ReadOnlyValue - &probability, // value - &seed, // value - &setRandomConnectivity, // dest - &setEntry, // dest - &unsetEntry, //dest - &clear, //dest - &transpose, //dest - &pairFill, //dest - &tripletFill, //dest - &tripletFill1, //dest - }; - - static Dinfo< short > dinfo; - static Cinfo sparseMsgCinfo ( - "SparseMsg", // name - Msg::initCinfo(), // base class - sparseMsgFinfos, - sizeof( sparseMsgFinfos ) / sizeof( Finfo* ), // num Fields - &dinfo - ); - - return &sparseMsgCinfo; + static Finfo* sparseMsgFinfos[] = + { + &numRows, // readonly value + &numColumns, // readonly value + &numEntries, // readonly value + &connectionList, // value + &matrixEntry, // ReadOnlyValue + &columnIndex, // ReadOnlyValue + &rowStart, // ReadOnlyValue + &probability, // value + &seed, // value + &setRandomConnectivity, // dest + &setEntry, // dest + &unsetEntry, //dest + &clear, //dest + &transpose, //dest + &pairFill, //dest + &tripletFill, //dest + &tripletFill1, //dest + }; + + static Dinfo< short > dinfo; + static Cinfo sparseMsgCinfo ( + "SparseMsg", // name + Msg::initCinfo(), // base class + sparseMsgFinfos, + sizeof( sparseMsgFinfos ) / sizeof( Finfo* ), // num Fields + &dinfo + ); + + return &sparseMsgCinfo; } static const Cinfo* sparseMsgCinfo = SparseMsg::initCinfo(); @@ -185,41 +186,44 @@ static const Cinfo* sparseMsgCinfo = SparseMsg::initCinfo(); ////////////////////////////////////////////////////////////////// void SparseMsg::setProbability ( double probability ) { - p_ = probability; - mtseed( seed_ ); - randomConnect( probability ); + p_ = probability; + randomConnect( probability ); } double SparseMsg::getProbability ( ) const { - return p_; + return p_; } -void SparseMsg::setSeed ( long seed ) +void SparseMsg::setSeed ( unsigned long seed ) { - seed_ = seed; - mtseed( seed_ ); - randomConnect( p_ ); + if( seed > 0 ) + seed_ = seed; + else + seed_ = rd_(); + + rng_.seed( seed_ ); + randomConnect( p_ ); } -long SparseMsg::getSeed () const +unsigned long SparseMsg::getSeed () const { - return seed_; + return seed_; } unsigned int SparseMsg::getNumRows() const { - return matrix_.nRows(); + return matrix_.nRows(); } unsigned int SparseMsg::getNumColumns() const { - return matrix_.nColumns(); + return matrix_.nColumns(); } unsigned int SparseMsg::getNumEntries() const { - return matrix_.nEntries(); + return matrix_.nEntries(); } vector< unsigned int > SparseMsg::getMatrixEntry() const @@ -239,24 +243,25 @@ vector< unsigned int > SparseMsg::getRowStart() const void SparseMsg::setEntryPairs( vector< unsigned int > v ) { - vector< unsigned int > src( v.begin(), v.begin() + v.size()/2 ); - vector< unsigned int > dest( v.begin() + v.size()/2, v.end() ); - pairFill( src, dest ); + vector< unsigned int > src( v.begin(), v.begin() + v.size()/2 ); + vector< unsigned int > dest( v.begin() + v.size()/2, v.end() ); + pairFill( src, dest ); } vector< unsigned int > SparseMsg::getEntryPairs() const { - vector< unsigned int > cols = matrix_.colIndex(); - vector< unsigned int > y; - for ( unsigned int row = 0; row < matrix_.nRows(); ++row ) { - unsigned int begin = matrix_.rowStart()[row]; - unsigned int end = matrix_.rowStart()[row+1]; - for ( unsigned int j = begin; j < end; ++j ) - y.push_back( row ); - } - assert( cols.size() == y.size() ); - y.insert( y.end(), cols.begin(), cols.end() ); - return y; + vector< unsigned int > cols = matrix_.colIndex(); + vector< unsigned int > y; + for ( unsigned int row = 0; row < matrix_.nRows(); ++row ) + { + unsigned int begin = matrix_.rowStart()[row]; + unsigned int end = matrix_.rowStart()[row+1]; + for ( unsigned int j = begin; j < end; ++j ) + y.push_back( row ); + } + assert( cols.size() == y.size() ); + y.insert( y.end(), cols.begin(), cols.end() ); + return y; } ////////////////////////////////////////////////////////////////// @@ -265,109 +270,115 @@ vector< unsigned int > SparseMsg::getEntryPairs() const void SparseMsg::setRandomConnectivity( double probability, long seed ) { - p_ = probability; - seed_ = seed; - mtseed( seed ); - randomConnect( probability ); + p_ = probability; + rng_.seed( seed ); + randomConnect( probability ); } void SparseMsg::setEntry( - unsigned int row, unsigned int column, unsigned int value ) + unsigned int row, unsigned int column, unsigned int value ) { - matrix_.set( row, column, value ); + matrix_.set( row, column, value ); } void SparseMsg::unsetEntry( unsigned int row, unsigned int column ) { - matrix_.unset( row, column ); + matrix_.unset( row, column ); } void SparseMsg::clear() { - matrix_.clear(); + matrix_.clear(); } void SparseMsg::transpose() { - matrix_.transpose(); - e1()->markRewired(); - e2()->markRewired(); + matrix_.transpose(); + e1()->markRewired(); + e2()->markRewired(); } void SparseMsg::updateAfterFill() { - unsigned int startData = e2_->localDataStart(); - unsigned int endData = startData + e2_->numLocalData(); - SparseMatrix< unsigned int > temp( matrix_); - temp.transpose(); - for ( unsigned int i = 0; i < temp.nRows(); ++ i ) { - const unsigned int* colIndex; - const unsigned int* entry; - unsigned int num = temp.getRow( i, &entry, &colIndex ); - if ( i >= startData && i < endData ) { - // Inefficient. Better to do it in one pass after getting - // the max num - e2_->resizeField( i - startData, num + 1 ); - } - } - e1()->markRewired(); - e2()->markRewired(); + unsigned int startData = e2_->localDataStart(); + unsigned int endData = startData + e2_->numLocalData(); + SparseMatrix< unsigned int > temp( matrix_); + temp.transpose(); + for ( unsigned int i = 0; i < temp.nRows(); ++ i ) + { + const unsigned int* colIndex; + const unsigned int* entry; + unsigned int num = temp.getRow( i, &entry, &colIndex ); + if ( i >= startData && i < endData ) + { + // Inefficient. Better to do it in one pass after getting + // the max num + e2_->resizeField( i - startData, num + 1 ); + } + } + e1()->markRewired(); + e2()->markRewired(); } void SparseMsg::pairFill( vector< unsigned int > src, - vector< unsigned int> dest ) -{ - // Sanity check - vector< unsigned int >::const_iterator i; - for ( i = src.begin(); i != src.end(); ++i ) { - if (*i >= e1()->numData() ) { - cout << "Warning: SparseMsg::pairFill: Src index " << *i << - " exceeds Src array size " << e1()->numData() << - ". Aborting\n"; - return; - } - } - for ( i = dest.begin(); i != dest.end(); ++i ) { - if (*i >= e2()->numData() ) { - cout << "Warning: SparseMsg::pairFill: Dest index " << *i << - " exceeds Dest array size " << e2()->numData() << - ". Aborting\n"; - return; - } - } - - vector< unsigned int > numAtDest( dest.size(), 0 ); - vector< unsigned int > fieldIndex( dest.size(), 0 ); - for ( unsigned int i = 0; i < dest.size(); ++i ) { - fieldIndex[i] = numAtDest[ dest[i] ]; - // Could do on previous line, but clarity - ++numAtDest[ dest[i] ]; - } - - /** - * We set retainSize flag to true since the # of src/dest objects - * doesn't change. We can explicitly assign it elsewhere if needed. - */ - matrix_.tripletFill( src, dest, fieldIndex, true ); - updateAfterFill(); + vector< unsigned int> dest ) +{ + // Sanity check + vector< unsigned int >::const_iterator i; + for ( i = src.begin(); i != src.end(); ++i ) + { + if (*i >= e1()->numData() ) + { + cout << "Warning: SparseMsg::pairFill: Src index " << *i << + " exceeds Src array size " << e1()->numData() << + ". Aborting\n"; + return; + } + } + for ( i = dest.begin(); i != dest.end(); ++i ) + { + if (*i >= e2()->numData() ) + { + cout << "Warning: SparseMsg::pairFill: Dest index " << *i << + " exceeds Dest array size " << e2()->numData() << + ". Aborting\n"; + return; + } + } + + vector< unsigned int > numAtDest( dest.size(), 0 ); + vector< unsigned int > fieldIndex( dest.size(), 0 ); + for ( unsigned int i = 0; i < dest.size(); ++i ) + { + fieldIndex[i] = numAtDest[ dest[i] ]; + // Could do on previous line, but clarity + ++numAtDest[ dest[i] ]; + } + + /** + * We set retainSize flag to true since the # of src/dest objects + * doesn't change. We can explicitly assign it elsewhere if needed. + */ + matrix_.tripletFill( src, dest, fieldIndex, true ); + updateAfterFill(); } void SparseMsg::tripletFill( vector< unsigned int > src, - vector< unsigned int> destDataIndex, - vector< unsigned int> destFieldIndex ) + vector< unsigned int> destDataIndex, + vector< unsigned int> destFieldIndex ) { - // We set retainSize flag to true - matrix_.tripletFill( src, destDataIndex, destFieldIndex, true ); - updateAfterFill(); + // We set retainSize flag to true + matrix_.tripletFill( src, destDataIndex, destFieldIndex, true ); + updateAfterFill(); } void SparseMsg::tripletFill1( vector< unsigned int > v ) { - unsigned int s3 = v.size() / 3; - vector< unsigned int > src( v.begin(), v.begin() + s3 ); - vector< unsigned int > dest( v.begin() + s3, v.begin() + 2 * s3 ); - vector< unsigned int > fieldIndex( v.begin() + 2 * s3, v.end() ); - tripletFill( src, dest, fieldIndex ); + unsigned int s3 = v.size() / 3; + vector< unsigned int > src( v.begin(), v.begin() + s3 ); + vector< unsigned int > dest( v.begin() + s3, v.begin() + 2 * s3 ); + vector< unsigned int > fieldIndex( v.begin() + 2 * s3, v.end() ); + tripletFill( src, dest, fieldIndex ); } ////////////////////////////////////////////////////////////////// @@ -376,59 +387,70 @@ void SparseMsg::tripletFill1( vector< unsigned int > v ) SparseMsg::SparseMsg( Element* e1, Element* e2, unsigned int msgIndex ) - : Msg( ObjId( managerId_, (msgIndex != 0) ? msgIndex: msg_.size() ), - e1, e2 ), - numThreads_( 1 ), - nrows_( 0 ), - p_( 0.0 ), seed_( 0 ) -{ - unsigned int nrows = 0; - unsigned int ncolumns = 0; - nrows = e1->numData(); - ncolumns = e2->numData(); - matrix_.setSize( nrows, ncolumns ); - if ( msgIndex == 0 ) { - msg_.push_back( this ); - } else { - if ( msg_.size() <= msgIndex ) - msg_.resize( msgIndex + 1 ); - msg_[ msgIndex ] = this; - } - - // cout << Shell::myNode() << ": SparseMsg constructor between " << e1->getName() << " and " << e2->getName() << endl; + : Msg( ObjId( managerId_, (msgIndex != 0) ? msgIndex: msg_.size() ), + e1, e2 ), + numThreads_( 1 ), + nrows_( 0 ), + p_( 0.0 ), seed_( 0 ) +{ + unsigned int nrows = 0; + unsigned int ncolumns = 0; + nrows = e1->numData(); + ncolumns = e2->numData(); + matrix_.setSize( nrows, ncolumns ); + if ( msgIndex == 0 ) + { + msg_.push_back( this ); + } + else + { + if ( msg_.size() <= msgIndex ) + msg_.resize( msgIndex + 1 ); + msg_[ msgIndex ] = this; + } + + // cout << Shell::myNode() << ": SparseMsg constructor between " << e1->getName() << " and " << e2->getName() << endl; + + // Init rng with random device. + if( seed_ == 0 ) + rng_.seed( rd_() ); } SparseMsg::~SparseMsg() { - assert( mid_.dataIndex < msg_.size() ); - msg_[ mid_.dataIndex ] = 0; // ensure deleted ptr isn't reused. + assert( mid_.dataIndex < msg_.size() ); + msg_[ mid_.dataIndex ] = 0; // ensure deleted ptr isn't reused. } unsigned int rowIndex( const Element* e, const DataId& d ) { - // FieldDataHandlerBase* fdh = dynamic_cast< FieldDataHandlerBase* >( e->dataHandler() ); + // FieldDataHandlerBase* fdh = dynamic_cast< FieldDataHandlerBase* >( e->dataHandler() ); - return d; + return d; } Eref SparseMsg::firstTgt( const Eref& src ) const { - if ( matrix_.nEntries() == 0 ) - return Eref( 0, 0 ); - - if ( src.element() == e1_ ) { - const unsigned int* fieldIndex; - const unsigned int* colIndex; - unsigned int n = matrix_.getRow( src.dataIndex(), - &fieldIndex, &colIndex ); - if ( n != 0 ) { - return Eref( e2_, colIndex[0], fieldIndex[0] ); - } - } else if ( src.element() == e2_ ) { - return Eref( e1_, 0 ); - } - return Eref( 0, 0 ); + if ( matrix_.nEntries() == 0 ) + return Eref( 0, 0 ); + + if ( src.element() == e1_ ) + { + const unsigned int* fieldIndex; + const unsigned int* colIndex; + unsigned int n = matrix_.getRow( src.dataIndex(), + &fieldIndex, &colIndex ); + if ( n != 0 ) + { + return Eref( e2_, colIndex[0], fieldIndex[0] ); + } + } + else if ( src.element() == e2_ ) + { + return Eref( e1_, 0 ); + } + return Eref( 0, 0 ); } /** @@ -442,163 +464,184 @@ Eref SparseMsg::firstTgt( const Eref& src ) const */ unsigned int SparseMsg::randomConnect( double probability ) { - unsigned int nRows = matrix_.nRows(); // Sources - unsigned int nCols = matrix_.nColumns(); // Destinations - matrix_.clear(); - unsigned int totalSynapses = 0; - vector< unsigned int > sizes( nCols, 0 ); - unsigned int totSynNum = 0; - Element* syn = e2_; - unsigned int startData = syn->localDataStart(); - unsigned int endData = startData + syn->numLocalData(); - - assert( nCols == syn->numData() ); - - matrix_.transpose(); - for ( unsigned int i = 0; i < nCols; ++i ) { - vector< unsigned int > synIndex; - // This needs to be obtained from current size of syn array. - // unsigned int synNum = sizes[ i ]; - unsigned int synNum = 0; - for ( unsigned int j = 0; j < nRows; ++j ) { - double r = mtrand(); // Want to ensure it is called each time round the loop. - if ( r < probability ) { - synIndex.push_back( synNum ); - ++synNum; - ++totSynNum; - } else { - synIndex.push_back( ~0 ); - } - } - - if ( i >= startData && i < endData ) { - e2_->resizeField( i - startData, synNum ); - } - totalSynapses += synNum; - matrix_.addRow( i, synIndex ); - /* - * This is the correct form, but I need to implement something - * to check up for target nodes in order to use this. - if ( i >= startData && i < endData ) { - e2_->resizeField( i - startData, synNum ); - totalSynapses += synNum; - matrix_.addRow( i, synIndex ); - } else { - synIndex.resize( 0 ); - synIndex.assign( nRows, ~0 ); - matrix_.addRow( i, synIndex ); - } - */ - } - - matrix_.transpose(); - // cout << Shell::myNode() << ": sizes.size() = " << sizes.size() << ", ncols = " << nCols << ", startSynapse = " << startSynapse << endl; - e1()->markRewired(); - e2()->markRewired(); - return totalSynapses; + unsigned int nRows = matrix_.nRows(); // Sources + unsigned int nCols = matrix_.nColumns(); // Destinations + matrix_.clear(); + unsigned int totalSynapses = 0; + vector< unsigned int > sizes( nCols, 0 ); + unsigned int totSynNum = 0; + Element* syn = e2_; + unsigned int startData = syn->localDataStart(); + unsigned int endData = startData + syn->numLocalData(); + + assert( nCols == syn->numData() ); + + matrix_.transpose(); + for ( unsigned int i = 0; i < nCols; ++i ) + { + vector< unsigned int > synIndex; + // This needs to be obtained from current size of syn array. + // unsigned int synNum = sizes[ i ]; + unsigned int synNum = 0; + for ( unsigned int j = 0; j < nRows; ++j ) + { + double r = dist_( rng_ ); // Want to ensure it is called each time round the loop. + if ( r < probability ) + { + synIndex.push_back( synNum ); + ++synNum; + ++totSynNum; + } + else + { + synIndex.push_back( ~0 ); + } + } + + if ( i >= startData && i < endData ) + { + e2_->resizeField( i - startData, synNum ); + } + totalSynapses += synNum; + matrix_.addRow( i, synIndex ); + /* + * This is the correct form, but I need to implement something + * to check up for target nodes in order to use this. + if ( i >= startData && i < endData ) { + e2_->resizeField( i - startData, synNum ); + totalSynapses += synNum; + matrix_.addRow( i, synIndex ); + } else { + synIndex.resize( 0 ); + synIndex.assign( nRows, ~0 ); + matrix_.addRow( i, synIndex ); + } + */ + } + + matrix_.transpose(); + // cout << Shell::myNode() << ": sizes.size() = " << sizes.size() << ", ncols = " << nCols << ", startSynapse = " << startSynapse << endl; + e1()->markRewired(); + e2()->markRewired(); + return totalSynapses; } Id SparseMsg::managerId() const { - return SparseMsg::managerId_; + return SparseMsg::managerId_; } void SparseMsg::setMatrix( const SparseMatrix< unsigned int >& m ) { - matrix_ = m; + matrix_ = m; } SparseMatrix< unsigned int >& SparseMsg::getMatrix( ) { - return matrix_; + return matrix_; } ObjId SparseMsg::findOtherEnd( ObjId f ) const { - if ( f.element() == e1() ) { - const unsigned int* entry; - const unsigned int* colIndex; - unsigned int num = matrix_.getRow( f.dataIndex, &entry, &colIndex ); - if ( num > 0 ) { // Return the first matching entry. - return ObjId( e2()->id(), colIndex[0] ); - } - return ObjId( 0, BADINDEX ); - } else if ( f.element() == e2() ) { // Bad! Slow! Avoid! - vector< unsigned int > entry; - vector< unsigned int > rowIndex; - unsigned int num = matrix_.getColumn( f.dataIndex, entry, rowIndex ); - if ( num > 0 ) { // Return the first matching entry. - return ObjId( e1()->id(), DataId( rowIndex[0] ) ); - } - } - return ObjId( 0, BADINDEX ); + if ( f.element() == e1() ) + { + const unsigned int* entry; + const unsigned int* colIndex; + unsigned int num = matrix_.getRow( f.dataIndex, &entry, &colIndex ); + if ( num > 0 ) // Return the first matching entry. + { + return ObjId( e2()->id(), colIndex[0] ); + } + return ObjId( 0, BADINDEX ); + } + else if ( f.element() == e2() ) // Bad! Slow! Avoid! + { + vector< unsigned int > entry; + vector< unsigned int > rowIndex; + unsigned int num = matrix_.getColumn( f.dataIndex, entry, rowIndex ); + if ( num > 0 ) // Return the first matching entry. + { + return ObjId( e1()->id(), DataId( rowIndex[0] ) ); + } + } + return ObjId( 0, BADINDEX ); } Msg* SparseMsg::copy( Id origSrc, Id newSrc, Id newTgt, - FuncId fid, unsigned int b, unsigned int n ) const -{ - const Element* orig = origSrc.element(); - if ( n <= 1 ) { - SparseMsg* ret = 0; - if ( orig == e1() ) { - ret = new SparseMsg( newSrc.element(), newTgt.element(), 0 ); - ret->e1()->addMsgAndFunc( ret->mid(), fid, b ); - } else if ( orig == e2() ) { - ret = new SparseMsg( newTgt.element(), newSrc.element(), 0 ); - ret->e2()->addMsgAndFunc( ret->mid(), fid, b ); - } else { - assert( 0 ); - } - ret->setMatrix( matrix_ ); - ret->nrows_ = nrows_; - return ret; - } else { - // Here we need a SliceMsg which goes from one 2-d array to another. - cout << "Error: SparseMsg::copy: SparseSliceMsg not yet implemented\n"; - return 0; - } + FuncId fid, unsigned int b, unsigned int n ) const +{ + const Element* orig = origSrc.element(); + if ( n <= 1 ) + { + SparseMsg* ret = 0; + if ( orig == e1() ) + { + ret = new SparseMsg( newSrc.element(), newTgt.element(), 0 ); + ret->e1()->addMsgAndFunc( ret->mid(), fid, b ); + } + else if ( orig == e2() ) + { + ret = new SparseMsg( newTgt.element(), newSrc.element(), 0 ); + ret->e2()->addMsgAndFunc( ret->mid(), fid, b ); + } + else + { + assert( 0 ); + } + ret->setMatrix( matrix_ ); + ret->nrows_ = nrows_; + return ret; + } + else + { + // Here we need a SliceMsg which goes from one 2-d array to another. + cout << "Error: SparseMsg::copy: SparseSliceMsg not yet implemented\n"; + return 0; + } } void fillErefsFromMatrix( - const SparseMatrix< unsigned int >& matrix, - vector< vector < Eref > >& v, Element* e1, Element* e2 ) -{ - v.clear(); - v.resize( e1->numData() ); - assert( e1->numData() == matrix.nRows() ); - assert( e2->numData() == matrix.nColumns() ); - for ( unsigned int i = 0; i < e1->numData(); ++i ) { - const unsigned int* entry; - const unsigned int* colIndex; - unsigned int num = matrix.getRow( i, &entry, &colIndex ); - v[i].resize( num ); - for ( unsigned int j = 0; j < num; ++j ) { - v[i][j] = Eref( e2, colIndex[j], entry[j] ); - } - } + const SparseMatrix< unsigned int >& matrix, + vector< vector < Eref > >& v, Element* e1, Element* e2 ) +{ + v.clear(); + v.resize( e1->numData() ); + assert( e1->numData() == matrix.nRows() ); + assert( e2->numData() == matrix.nColumns() ); + for ( unsigned int i = 0; i < e1->numData(); ++i ) + { + const unsigned int* entry; + const unsigned int* colIndex; + unsigned int num = matrix.getRow( i, &entry, &colIndex ); + v[i].resize( num ); + for ( unsigned int j = 0; j < num; ++j ) + { + v[i][j] = Eref( e2, colIndex[j], entry[j] ); + } + } } void SparseMsg::sources( vector< vector < Eref > >& v ) const { - SparseMatrix< unsigned int > temp( matrix_ ); - temp.transpose(); - fillErefsFromMatrix( temp, v, e2_, e1_ ); + SparseMatrix< unsigned int > temp( matrix_ ); + temp.transpose(); + fillErefsFromMatrix( temp, v, e2_, e1_ ); } void SparseMsg::targets( vector< vector< Eref > >& v ) const { - fillErefsFromMatrix( matrix_, v, e1_, e2_ ); + fillErefsFromMatrix( matrix_, v, e1_, e2_ ); } /// Static function for Msg access unsigned int SparseMsg::numMsg() { - return msg_.size(); + return msg_.size(); } /// Static function for Msg access char* SparseMsg::lookupMsg( unsigned int index ) { - assert( index < msg_.size() ); - return reinterpret_cast< char* >( msg_[index] ); + assert( index < msg_.size() ); + return reinterpret_cast< char* >( msg_[index] ); } diff --git a/moose-core/msg/SparseMsg.h b/moose-core/msg/SparseMsg.h index 3d7ba580a1c19cc6ea22e54b2202d41f2285228e..0061a9fe4f30d183667fa19b17e2992c40599fee 100644 --- a/moose-core/msg/SparseMsg.h +++ b/moose-core/msg/SparseMsg.h @@ -10,6 +10,8 @@ #ifndef _SPARSE_MSG_H #define _SPARSE_MSG_H +#include "../randnum/RNG.h" + /** * This is a parallelized sparse message. * It is a general message type optimized for sparse matrix like @@ -27,6 +29,7 @@ * Synapses, which are array fields of IntFire objects. * The sparse connectivity maps between the source IntFire and target * Synapses. + * * The location of the entry in the sparse matrix provides the index of * the target IntFire. * The data value in the sparse matrix provides the index of the Synapse @@ -39,113 +42,117 @@ * BiSparseMsg. * It can be modified after creation to add or remove message entries. */ + class SparseMsg: public Msg { - friend unsigned int Msg::initMsgManagers(); // for initializing Id. - public: - SparseMsg( Element* e1, Element* e2, unsigned int msgIndex ); - ~SparseMsg(); - - Eref firstTgt( const Eref& src ) const; - - void sources( vector< vector< Eref > >& v ) const; - void targets( vector< vector< Eref > >& v ) const; - - unsigned int randomConnect( double probability ); - - Id managerId() const; - - ObjId findOtherEnd( ObjId end ) const; - - Msg* copy( Id origSrc, Id newSrc, Id newTgt, - FuncId fid, unsigned int b, unsigned int n ) const; - - /** - * Assigns the whole connection matrix - */ - void setMatrix( const SparseMatrix< unsigned int >& m ); - - /** - * Returns the connection matrix - */ - SparseMatrix< unsigned int >& getMatrix(); - - // Uses default addToQ function. - - ///////////////////////////////////////////////////////////////// - // Here we define the Element interface functions for SparseMsg - ///////////////////////////////////////////////////////////////// - void setRandomConnectivity( double probability, long seed ); - double getProbability() const; - void setProbability( double value ); - - // - vector< unsigned int > getMatrixEntry() const; - vector< unsigned int > getColIndex() const; - vector< unsigned int > getRowStart() const; - - long getSeed() const; - void setSeed( long value ); - - vector< unsigned int > getEntryPairs() const; - void setEntryPairs( vector< unsigned int > entries ); - - void setEntry( unsigned int row, unsigned int column, - unsigned int value ); - - void unsetEntry( unsigned int row, unsigned int column ); - - // Still need to implement array field gets. - - unsigned int getNumRows() const; - unsigned int getNumColumns() const; - unsigned int getNumEntries() const; - void clear(); - void transpose(); - - /** - * Fills up the entire message based on pairs of src,dest (i.e., - * row,column) values. All filled entries are set to zero. - */ - void pairFill( vector< unsigned int > src, - vector< unsigned int> dest ); - - /** - * Fills up the entire message based on triplets of - * src,destDataIndex,destFieldIndex - */ - void tripletFill( vector< unsigned int > src, - vector< unsigned int> dest, - vector< unsigned int > field ); - - /** - * Fills up the entire message based on triplets of - * src,destDataIndex,destFieldIndex, but catenates them all into - * a single long vector since PyMoose doesn't know how to handle - * multiple vectors. - */ - void tripletFill1( vector< unsigned int > entries ); - - /** - * Utility function to update all sorts of values after we've - * rebuilt the matrix. - */ - void updateAfterFill(); - - /// Msg lookup functions - static unsigned int numMsg(); - static char* lookupMsg( unsigned int index ); - - static const Cinfo* initCinfo(); - - private: - SparseMatrix< unsigned int > matrix_; - unsigned int numThreads_; // Number of threads to partition - unsigned int nrows_; // The original size of the matrix. - double p_; - unsigned long seed_; - static Id managerId_; // The Element that manages Sparse Msgs. - static vector< SparseMsg* > msg_; + friend unsigned int Msg::initMsgManagers(); // for initializing Id. + +public: + + SparseMsg( Element* e1, Element* e2, unsigned int msgIndex ); + ~SparseMsg(); + + Eref firstTgt( const Eref& src ) const; + + void sources( vector< vector< Eref > >& v ) const; + void targets( vector< vector< Eref > >& v ) const; + + unsigned int randomConnect( double probability ); + + Id managerId() const; + + ObjId findOtherEnd( ObjId end ) const; + + Msg* copy( Id origSrc, Id newSrc, Id newTgt, + FuncId fid, unsigned int b, unsigned int n ) const; + + /** + * Assigns the whole connection matrix + */ + void setMatrix( const SparseMatrix< unsigned int >& m ); + + /** + * Returns the connection matrix + */ + SparseMatrix< unsigned int >& getMatrix(); + + // Uses default addToQ function. + + // Here we define the Element interface functions for SparseMsg + void setRandomConnectivity( double probability, long seed ); + double getProbability() const; + void setProbability( double value ); + + vector< unsigned int > getMatrixEntry() const; + vector< unsigned int > getColIndex() const; + vector< unsigned int > getRowStart() const; + + unsigned long getSeed() const; + void setSeed( unsigned long value ); + + vector< unsigned int > getEntryPairs() const; + void setEntryPairs( vector< unsigned int > entries ); + + void setEntry( unsigned int row, unsigned int column, + unsigned int value ); + + void unsetEntry( unsigned int row, unsigned int column ); + + // Still need to implement array field gets. + unsigned int getNumRows() const; + unsigned int getNumColumns() const; + unsigned int getNumEntries() const; + void clear(); + void transpose(); + + /** + * Fills up the entire message based on pairs of src,dest (i.e., + * row,column) values. All filled entries are set to zero. + */ + void pairFill( vector< unsigned int > src, + vector< unsigned int> dest ); + + /** + * Fills up the entire message based on triplets of + * src,destDataIndex,destFieldIndex + */ + void tripletFill( vector< unsigned int > src, + vector< unsigned int> dest, + vector< unsigned int > field ); + + /** + * Fills up the entire message based on triplets of + * src,destDataIndex,destFieldIndex, but catenates them all into + * a single long vector since PyMoose doesn't know how to handle + * multiple vectors. + */ + void tripletFill1( vector< unsigned int > entries ); + + /** + * Utility function to update all sorts of values after we've + * rebuilt the matrix. + */ + void updateAfterFill(); + + /// Msg lookup functions + static unsigned int numMsg(); + static char* lookupMsg( unsigned int index ); + + static const Cinfo* initCinfo(); + +private: + SparseMatrix< unsigned int > matrix_; + unsigned int numThreads_; // Number of threads to partition + unsigned int nrows_; // The original size of the matrix. + double p_; + static Id managerId_; // The Element that manages Sparse Msgs. + static vector< SparseMsg* > msg_; + + // RNG. + unsigned long seed_; + moose::MOOSE_RANDOM_DEVICE rd_; + moose::MOOSE_RNG_DEFAULT_ENGINE rng_; + moose::MOOSE_UNIFORM_DISTRIBUTION<double> dist_; }; #endif // _SPARSE_MSG_H diff --git a/moose-core/pymoose/CMakeLists.txt b/moose-core/pymoose/CMakeLists.txt index b5d118b764800099c1753c54876237d34de57b54..3c69dacdc764bede7bb78324b759f653141bde4e 100644 --- a/moose-core/pymoose/CMakeLists.txt +++ b/moose-core/pymoose/CMakeLists.txt @@ -1,5 +1,4 @@ -add_definitions(-DPYMOOSE) -include_directories(../basecode ../msg) +cmake_minimum_required(VERSION 2.8) set(PYMOOSE_SRCS moosemodule.cpp @@ -7,8 +6,8 @@ set(PYMOOSE_SRCS mfield.cpp pymooseinit.cpp melement.cpp - test_moosemodule.cpp PyRun.cpp + test_moosemodule.cpp ) # Build _moose.so in source directory and them copy everything to @@ -35,15 +34,20 @@ add_definitions(-DUSE_NUMPY) add_definitions(-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION) -execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --includes - OUTPUT_VARIABLE PYTHON_INCLUDE_FLAGS - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --libs - OUTPUT_VARIABLE PYTHON_LIBRARIES - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -message( STATUS "Python include flags: ${PYTHON_INCLUDE_FLAGS}" ) +# make sure the Python.h is found. +find_package( PythonLibs REQUIRED) +include_directories( ${PYTHON_INCLUDE_DIRS} ) + +#execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --includes +# OUTPUT_VARIABLE PYTHON_INCLUDE_FLAGS +# OUTPUT_STRIP_TRAILING_WHITESPACE +# ) +#execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --libs +# OUTPUT_VARIABLE PYTHON_LIBRARIES +# OUTPUT_STRIP_TRAILING_WHITESPACE +# ) +# message( STATUS "Python include flags: ${PYTHON_INCLUDE_FLAGS}" ) + set_target_properties(_moose PROPERTIES COMPILE_DEFINITIONS "PYMOOSE" COMPILE_FLAGS "${PYTHON_INCLUDE_FLAGS}" @@ -62,7 +66,6 @@ if(HDF5_LIBRARY_DIRS) set_target_properties( _moose PROPERTIES LINK_FLAGS "-L${HDF5_LIBRARY_DIRS}" ) endif() - if(MACOSX) set(CMAKE_MODULE_LINKER_FLAGS "-undefined dynamic_lookup") message(STATUS "ADDING some linker flags ${CMAKE_EXE_LINKER_FLAGS}") @@ -83,7 +86,6 @@ else(MACOSX) ${MOOSE_LIBRARIES} ${STATIC_LIBRARIES} "-Wl,--no-whole-archive" - # ${PYTHON_LIBRARIES} ${SYSTEM_SHARED_LIBS} ) endif(MACOSX) diff --git a/moose-core/pymoose/melement.cpp b/moose-core/pymoose/melement.cpp index 82856488d2fe318e52b0e0a19081d9db45be4a13..47ce0e407d7dffaaeca1ce5e509425929d277ff6 100644 --- a/moose-core/pymoose/melement.cpp +++ b/moose-core/pymoose/melement.cpp @@ -49,7 +49,7 @@ #include <Python.h> #include <structmember.h> -#ifdef USE_BOOST +#ifdef USE_BOOST_ODE #include <boost/format.hpp> #endif diff --git a/moose-core/pymoose/mfield.cpp b/moose-core/pymoose/mfield.cpp index 7e73f2650e979d17ef72952699f4274121f3358c..9cb2b073706f74bf5a082f33379a0b5d7f23fe35 100644 --- a/moose-core/pymoose/mfield.cpp +++ b/moose-core/pymoose/mfield.cpp @@ -116,11 +116,12 @@ int moose_Field_init(_Field * self, PyObject * args, PyObject * kwargs) } self->owner = ((_ObjId*)owner); Py_INCREF(self->owner); - ObjId tmp = ((_ObjId*)owner)->oid_; - size_t size = strlen(fieldName); - char * name = (char*)calloc(size+1, sizeof(char)); - strncpy(name, fieldName, size); - self->name = name; + self->name = strdup(fieldName); + if (!self->name) { + PyErr_NoMemory(); + return -1; + } + // In earlier version I tried to deallocate the existing // self->name if it is not NULL. But it turns out that it // causes a SIGABRT. In any case it should not be an issue as @@ -316,7 +317,7 @@ PyObject * moose_DestField_call(PyObject * self, PyObject * args, PyObject * arg = PyTuple_GetItem(args, ii); Py_INCREF(arg); PyTuple_SetItem(newargs, ii+1, arg); - Py_DECREF(arg); + //Py_DECREF(arg); } // Call ObjId._setDestField with the new arguments PyObject * ret = moose_ObjId_setDestField(((_Field*)self)->owner, newargs); diff --git a/moose-core/pymoose/moosemodule.cpp b/moose-core/pymoose/moosemodule.cpp index ae638e18c3afc90267e20467fb89577ba9c95ba3..acf86f0235bb32feff830f6d6de8b6fd2c3eb859 100644 --- a/moose-core/pymoose/moosemodule.cpp +++ b/moose-core/pymoose/moosemodule.cpp @@ -20,7 +20,7 @@ #include <exception> -#if USE_BOOST +#if USE_BOOST_ODE #include <boost/format.hpp> #endif @@ -2536,66 +2536,6 @@ int defineLookupFinfos(const Cinfo * cinfo) return 1; } -int defineDestFinfos(const Cinfo * cinfo) -{ - const string& className = cinfo->name(); -#ifndef NDEBUG - if (verbosity > 1) - { - cout << "\tCreating destField attributes for " << className << endl; - } -#endif - vector <PyGetSetDef>& vec = get_getsetdefs()[className]; - /* - We do not know the final number of user-accessible - destFinfos as we have to ignore the destFinfos starting - with get/set. So use a vector instead of C array. - */ - size_t currIndex = vec.size(); - for (unsigned int ii = 0; ii < cinfo->getNumDestFinfo(); ++ii) - { - Finfo * destFinfo = const_cast<Cinfo*>(cinfo)->getDestFinfo(ii); - const string& name = destFinfo->name(); - /* - get_{xyz} and set_{xyz} are internal destFinfos for - accessing valueFinfos. Ignore them. - - With the '_' removed from internal get/set for value - fields, we cannot separate them out. - Subha Fri Jan 31 - 16:43:51 IST 2014 - - The policy changed in the past and hence the following were commented out. - - Subha Tue May 26 00:25:28 EDT 2015 - */ - // if (name.find("get") == 0 || name.find("set") == 0){ - // continue; - // } - PyGetSetDef destFieldGetSet; - vec.push_back(destFieldGetSet); - - vec[currIndex].name = (char*)calloc(name.size() + 1, sizeof(char)); - strncpy(vec[currIndex].name, - const_cast<char*>(name.c_str()), - name.size()); - - vec[currIndex].doc = (char*) "D_field"; - vec[currIndex].get = (getter)moose_ObjId_get_destField_attr; - PyObject * args = PyTuple_New(1); - if (args == NULL) - { - cerr << "moosemodule.cpp: defineDestFinfos: Failed to allocate tuple" << endl; - return 0; - } - PyTuple_SetItem(args, 0, PyString_FromString(name.c_str())); - vec[currIndex].closure = (void*)args; - - //LOG( debug, "\tCreated destField " << vec[currIndex].name ); - - ++currIndex; - } // ! for - - return 1; -} int defineClass(PyObject * module_dict, const Cinfo * cinfo) { @@ -2770,6 +2710,63 @@ PyObject * moose_ObjId_get_destField_attr(PyObject * self, void * closure) return (PyObject*)ret; } + +int defineDestFinfos(const Cinfo * cinfo) +{ + const string& className = cinfo->name(); +#ifndef NDEBUG + if (verbosity > 1) + { + cout << "\tCreating destField attributes for " << className << endl; + } +#endif + vector <PyGetSetDef>& vec = get_getsetdefs()[className]; + /* + We do not know the final number of user-accessible + destFinfos as we have to ignore the destFinfos starting + with get/set. So use a vector instead of C array. + */ + size_t currIndex = vec.size(); + for (unsigned int ii = 0; ii < cinfo->getNumDestFinfo(); ++ii) + { + Finfo * destFinfo = const_cast<Cinfo*>(cinfo)->getDestFinfo(ii); + const string& name = destFinfo->name(); + /* + get_{xyz} and set_{xyz} are internal destFinfos for + accessing valueFinfos. Ignore them. + + With the '_' removed from internal get/set for value + fields, we cannot separate them out. - Subha Fri Jan 31 + 16:43:51 IST 2014 + + The policy changed in the past and hence the following were commented out. + - Subha Tue May 26 00:25:28 EDT 2015 + */ + // if (name.find("get") == 0 || name.find("set") == 0){ + // continue; + // } + PyGetSetDef destFieldGetSet; + vec.push_back(destFieldGetSet); + + vec[currIndex].name = strdup(name.c_str()); + vec[currIndex].doc = (char*) "Destination field"; + vec[currIndex].get = (getter)moose_ObjId_get_destField_attr; + PyObject *args = PyTuple_New(1); + if (!args || !vec[currIndex].name) { + cerr << "moosemodule.cpp: defineDestFinfos: allocation failed\n"; + return 0; + } + PyTuple_SetItem(args, 0, PyString_FromString(name.c_str())); + vec[currIndex].closure = (void*)args; + + //LOG( debug, "\tCreated destField " << vec[currIndex].name ); + + ++currIndex; + } // ! for + + return 1; +} + /** Try to obtain a LookupField object for a specified lookupFinfo. The first item in `closure` must be the name of diff --git a/moose-core/python/moose/chemUtil/add_Delete_ChemicalSolver.py b/moose-core/python/moose/chemUtil/add_Delete_ChemicalSolver.py index cc350ec6087ac1b731b0a274b75eeeebb8a3de77..9b11a5c148c094ae2b125cf0407c1395dfad7db3 100644 --- a/moose-core/python/moose/chemUtil/add_Delete_ChemicalSolver.py +++ b/moose-core/python/moose/chemUtil/add_Delete_ChemicalSolver.py @@ -1,158 +1,140 @@ # -*- coding: utf-8 -*- +__author__ = "HarshaRani" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "HarshaRani" +__email__ = "hrani@ncbs.res.in" +__status__ = "Development" +__updated__ = "Sep 03 2018" + + +''' +mooseAddChemSolver and mooseDeleteChemSolver is for adding and deleting only +Chemical solver +''' + import moose -from fixXreacs import fixXreacs +from moose.fixXreacs import fixXreacs def positionCompt( compt ): i = 0 while (i != len(compt)-1): - #print "PositionCompt ", compt[i+1],compt[i+1].volume, compt[i], compt[i].volume compt[i+1].x1 += compt[i].x1 compt[i+1].x0 += compt[i].x1 i += 1 -def moosedeleteChemSolver(modelRoot): - """Delete solvers from Chemical Compartment +def mooseDeleteChemSolver(modelRoot): + """Delete solvers from Chemical Compartment """ - """ - compts = moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]') - for compt in compts: - if moose.exists(compt.path + '/stoich'): - st = moose.element(compt.path + '/stoich') - st_ksolve = st.ksolve - st_dsolve = st.dsolve - - moose.delete(st) - if moose.exists((st_ksolve).path): - moose.delete(st_ksolve) - print("KSolver is deleted for modelpath %s " % modelRoot) - if moose.exists((st_dsolve).path): - moose.delete(st_dsolve) - print("DSolver is deleted for modelpath %s " % modelRoot) - ''' compts = moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]') - for compt in compts: - if moose.exists(compt.path + '/stoich'): - st = moose.element(compt.path + '/stoich') - st_ksolve = st.ksolve - moose.delete(st) - if moose.exists((st_ksolve).path): - moose.delete(st_ksolve) - print("Solver is deleted for modelpath %s " % modelRoot) - - ''' - -def mooseaddChemSolver(modelRoot, solver): + if all(isinstance(x, (moose.CubeMesh,moose.CylMesh)) for x in compts): + for compt in compts: + if moose.exists(compt.path + '/stoich'): + st = moose.element(compt.path + '/stoich') + st_ksolve = st.ksolve + st_dsolve = st.dsolve + + moose.delete(st) + + if moose.exists((st_ksolve).path): + print("KSolver is deleted for modelpath %s " % st_ksolve) + moose.delete(st_ksolve) + + if moose.exists((st_dsolve).path) and st_dsolve.path != '/': + print("DSolver is deleted for modelpath %s " % st_dsolve) + moose.delete(st_dsolve) + else: + return ("mooseDeleteChemSolver is only for deleting Chemical Model solver which has to be `CubeMesh` or `CylMesh` found ",list(set([x.className for x in compts]) - set(['CubeMesh',"CylMesh"]))) + +def stdSolvertype(solverName): + if solverName.lower() in ["gssa","gillespie","stochastic","gsolve"]: + return "gssa" + elif solverName.lower() in ["gsl","runge kutta","deterministic","ksolve","rungekutta","rk5","rkf","rk"]: + return "gsl" + elif solverName.lower() in ["ee","exponential euler","exponentialeuler","neutral"]: + return "ee" + return "ee" + +def mooseAddChemSolver(modelRoot, solver): """ - Add the solvers to Chemical compartment + Add the solvers only if all are Chemical compartment """ - compt = moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]') - if compt: - comptinfo = moose.Annotator(moose.element(compt[0]).path + '/info') - previousSolver = comptinfo.solver - currentSolver = previousSolver - if solver == "Gillespie" or solver == "gssa": - currentSolver = "gssa" - elif solver == "Runge Kutta" or solver == "gsl": - currentSolver = "gsl" - elif solver == "Exponential Euler" or solver == "ee": - currentSolver = "ee" - - if previousSolver != currentSolver: - # if previousSolver != currentSolver - comptinfo.solver = currentSolver - if (moose.exists(compt[0].path + '/stoich')): - # "A: and stoich exists then delete the stoich add solver" - deleteSolver(modelRoot) - setCompartmentSolver(modelRoot, currentSolver) - return True - else: - # " B: stoich doesn't exists then addSolver, this is when object is deleted which delete's the solver " - # " and solver is also changed, then add addsolver " - setCompartmentSolver(modelRoot, currentSolver) - return True + compts = moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]') + if all(isinstance(x, (moose.CubeMesh,moose.CylMesh)) for x in compts): + if not compts: + return ("Atleast one compartment is required ") + elif ( len(compts) > 3 ): + return ("Warning: setSolverOnCompt Cannot handle " , len(compts) , " chemical compartments\n") + else: - if moose.exists(compt[0].path + '/stoich'): - # " stoich exist, doing nothing" - return False - else: - # "but stoich doesn't exist,this is when object is deleted which deletes the solver - # " but solver are not changed, then also call addSolver" + comptinfo = moose.Annotator(moose.element(compts[0]).path + '/info') + + previousSolver = stdSolvertype(comptinfo.solver) + currentSolver = stdSolvertype(solver) + + if previousSolver != currentSolver: + comptinfo.solver = currentSolver + if (moose.exists(compts[0].path + '/stoich')): + # "A: and stoich exists then delete the stoich add solver" + mooseDeleteChemSolver(modelRoot) setCompartmentSolver(modelRoot, currentSolver) return True - return False + else: + if not moose.exists(compts[0].path + '/stoich'): + # " stoich exist, doing nothing" + setCompartmentSolver(modelRoot, currentSolver) + return True + else: + + return ("mooseAddChemSolver is only for adding Chemical Model which has to be `CubeMesh` or `CylMesh` found ",list(set([x.className for x in compts]) - set(['CubeMesh',"CylMesh"]))) def setCompartmentSolver(modelRoot, solver): - comptlist = dict((c, c.volume) for c in moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]')) - comptVol = {} - compts = [] - vol = [v for k,v in comptlist.items()] - volumeSort = sorted(vol) - for k,v in comptlist.items(): - comptVol[k]= v - for volSor in volumeSort: - for a,b in comptVol.items(): - if b == volSor: - compts.append(a) - - #compts = [key for key, value in sorted(comptlist.items(), key=lambda (k,v): (v,k))] - if ( len(compts) == '0'): - print ("Atleast one compartment is required ") - return - else: - if ( len(compts) > 3 ): - print ("Warning: setSolverOnCompt Cannot handle " , len(compts) , " chemical compartments\n") - return; + """ + If Solver type is 'gsl' or 'gssa' do add Solver + if 'ee' nothing - elif (len(compts) >1 ): - positionCompt(compts) + """ + if solver != 'ee': + comptlist = dict((c.volume, c) for c in moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]')) + vollist = sorted(comptlist.keys()) + compts = [comptlist[key] for key in vollist] - fixXreacs( modelRoot ) + #compts = [key for key, value in sorted(comptlist.items(), key=lambda (k,v): (v,k))] + + if (len(compts) >1 ): + positionCompt(compts) + fixXreacs( modelRoot ) + + vollist = sorted(comptlist.keys()) + compts = [comptlist[key] for key in vollist] + #compts = [key for key, value in sorted(comptlist.items(), key=lambda (k,v): (v,k))] for compt in compts: if solver != 'ee': - if (solver == 'gsl') or (solver == 'Runge Kutta'): + if (solver == 'gsl'): ksolve = moose.Ksolve(compt.path + '/ksolve') - if (solver == 'gssa') or (solver == 'Gillespie'): + if (solver == 'gssa') : ksolve = moose.Gsolve(compt.path + '/gsolve') - - dsolve = moose.Dsolve(compt.path+'/dsolve') + + if (len(compts) > 1): + dsolve = moose.Dsolve(compt.path+'/dsolve') + stoich = moose.Stoich(compt.path + '/stoich') - stoich.compartment = compt stoich.ksolve = ksolve - stoich.dsolve = dsolve + if (len(compts) > 1): + stoich.dsolve = dsolve + + stoich.compartment = compt stoich.path = compt.path + "/##" - ksolveList = moose.wildcardFind(modelRoot+'/##[ISA=Ksolve]') + + dsolveList = moose.wildcardFind(modelRoot+'/##[ISA=Dsolve]') - stoichList = moose.wildcardFind(modelRoot+'/##[ISA=Stoich]') - i = 0 while(i < len(dsolveList)-1): dsolveList[i+1].buildMeshJunctions(dsolveList[i]) i += 1 - - print( " Solver is added to model path %s" % modelRoot ) - ''' - compts = moose.wildcardFind(modelRoot + '/##[ISA=ChemCompt]') - for compt in compts: - if (solver == 'gsl') or (solver == 'Runge Kutta'): - ksolve = moose.Ksolve(compt.path + '/ksolve') - if (solver == 'gssa') or (solver == 'Gillespie'): - ksolve = moose.Gsolve(compt.path + '/gsolve') - if (solver != 'ee'): - stoich = moose.Stoich(compt.path + '/stoich') - stoich.compartment = compt - stoich.ksolve = ksolve - if moose.exists(compt.path): - stoich.path = compt.path + "/##" - stoichList = moose.wildcardFind(modelRoot + '/##[ISA=Stoich]') - if len(stoichList) == 2: - stoichList[1].buildXreacs(stoichList[0]) - if len(stoichList) == 3: - stoichList[1].buildXreacs(stoichList[0]) - stoichList[1].buildXreacs(stoichList[2]) - - for i in stoichList: - i.filterXreacs() - print( " Solver is added to model path %s" % modelRoot ) - ''' + if not modelRoot[:1].startswith('/'): + modelRoot ='/'+modelRoot + print( " Solver is added to model path `%s` with `%s` solver" % (modelRoot,solver) ) diff --git a/moose-core/python/fixXreacs.py b/moose-core/python/moose/fixXreacs.py similarity index 100% rename from moose-core/python/fixXreacs.py rename to moose-core/python/moose/fixXreacs.py diff --git a/moose-core/python/moose/genesis/writeKkit.py b/moose-core/python/moose/genesis/writeKkit.py index c94ca3daddfc1e0a0215ccb04e84986c2c0fad8a..f6bba42b84394f8963b31d97240a88679f453f8c 100644 --- a/moose-core/python/moose/genesis/writeKkit.py +++ b/moose-core/python/moose/genesis/writeKkit.py @@ -224,9 +224,11 @@ def writeEnz( modelpath,f,sceneitems): concInit = 0; n = 0; conc = 0; - enzParent = enz.parent - if (isinstance(enzParent.className,moose.Pool)) or (isinstance(enzParent.className,moose.ZombiePool)): - print(" raise exception enz doesn't have pool as parent") + if len(moose.element(enz).neighbors['enzDest']) == 1: + enzParent = moose.element(moose.element(enz).neighbors['enzDest'][0]) + + if not (isinstance(enzParent,moose.PoolBase)): + print(" raise exception enz doesn't have pool as parent %s",moose.element(enz).path) return False else: vol = enzParent.volume * NA * 1e-3; diff --git a/moose-core/python/moose/moose.py b/moose-core/python/moose/moose.py index a949e5f4b5429952c38be7b9e2414694652dad9a..b9acb706279e4744800bed8e1690419953f63c40 100644 --- a/moose-core/python/moose/moose.py +++ b/moose-core/python/moose/moose.py @@ -10,7 +10,7 @@ from contextlib import closing import warnings import pydoc from io import StringIO - +from os.path import splitext import moose import moose.utils as mu @@ -62,6 +62,42 @@ except Exception as e: # Import function from C++ module into moose namespace. from moose._moose import * +#`loadModel` is deleted from global import, +# this is to bypass the call from c++ module which is due to fixXreacs() which is +# now written in python and readKkit.cpp will not be possible to set/call the solver due to this + +del globals()['loadModel'] + +def loadModel(filename, target,method=None): + solverClass = 'Neutral' + if method != None: + solverClass = method + try: + f = open(filename,'r') + f.close() + except IOError as e: + print (e) + return + else: + file_name,extension = splitext(filename) + if extension in [".swc",".p"]: + ret = moose._moose.loadModel(filename,target,"Neutral") + elif extension in [".g",".cspace"]: + #only if genesis or cspace file, then mooseAddChemSolver is called + ret = moose._moose.loadModel(filename,target,"ee") + + method = "ee" + if solverClass.lower() in ["gssa","gillespie","stochastic","gsolve"]: + method = "gssa" + elif solverClass.lower() in ["gsl","runge kutta","deterministic","ksolve","rungekutta","rk5","rkf","rk"]: + method = "gsl" + elif solverClass.lower() in ["exponential euler","exponentialeuler","neutral"]: + method = "ee" + + if method != 'ee': + chemError_ = _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(target,method) + return ret + def version( ): return VERSION @@ -149,20 +185,20 @@ def mooseWriteKkit(modelpath, filepath,sceneitems={}): return _writeKkit.mooseWriteKkit(modelpath, filepath,sceneitems) -def moosedeleteChemSolver(modelpath): +def mooseDeleteChemSolver(modelpath): """ deletes solver on all the compartment and its children. This is neccesary while created a new moose object on a pre-existing modelpath,\n - this should be followed by mooseaddChemSolver for add solvers on to compartment to simulate else + this should be followed by mooseAddChemSolver for add solvers on to compartment to simulate else default is Exponential Euler (ee) """ if chemImport_: - return _chemUtil.add_Delete_ChemicalSolver.moosedeleteChemSolver(modelpath) + return _chemUtil.add_Delete_ChemicalSolver.mooseDeleteChemSolver(modelpath) else: print( chemError_ ) return False -def mooseaddChemSolver(modelpath, solver): +def mooseAddChemSolver(modelpath, solver): """ Add solver on chemical compartment and its children for calculation keyword arguments:\n @@ -174,7 +210,8 @@ def mooseaddChemSolver(modelpath, solver): """ if chemImport_: - return _chemUtil.add_Delete_ChemicalSolver.mooseaddChemSolver(modelpath, solver) + chemError_ = _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath, solver) + return chemError_ else: print( chemError_ ) return False diff --git a/moose-core/python/moose/print_utils.py b/moose-core/python/moose/print_utils.py index 5cc08416a1c7784219272c2a779522d08f953748..e34062313057c38e4720e874dfd7b938f9b7f412 100644 --- a/moose-core/python/moose/print_utils.py +++ b/moose-core/python/moose/print_utils.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -# print_utils.py: -# # A library with some print functions. Very useful during development. from __future__ import print_function, division, absolute_import diff --git a/moose-core/python/rdesigneur/rdesigneur.py b/moose-core/python/rdesigneur/rdesigneur.py index 66a2ea68996ee4dae577254b438c40a2b9c72dc4..aa5b3fce4b5513a3579fae9e365687e7f24c6ce3 100644 --- a/moose-core/python/rdesigneur/rdesigneur.py +++ b/moose-core/python/rdesigneur/rdesigneur.py @@ -23,13 +23,14 @@ import os import moose import numpy as np import math -import itertools import sys import time +import matplotlib.pyplot as plt import rdesigneur.rmoogli as rmoogli from rdesigneur.rdesigneurProtos import * -import fixXreacs +from moose.fixXreacs import fixXreacs +#import fixXreacs #from . import fixXreacs #from rdesigneur.rmoogli import * #import rmoogli @@ -77,6 +78,8 @@ class rdesigneur: combineSegments = True, stealCellFromLibrary = False, verbose = True, + addSomaChemCompt = False, # Put a soma chemCompt on neuroMesh + addEndoChemCompt = False, # Put an endo compartment, typically for ER, on each of the NeuroMesh compartments. diffusionLength= 2e-6, meshLambda = -1.0, #This is a backward compatibility hack temperature = 32, @@ -87,6 +90,7 @@ class rdesigneur: elecPlotDt = 0.1e-3, # Same default as from MOOSE funcDt = 0.1e-3, # Used when turnOffElec is False. # Otherwise system uses chemDt. + numWaveFrames = 100, # Number of frames to use for waveplots cellProto = [], spineProto = [], chanProto = [], @@ -97,8 +101,8 @@ class rdesigneur: chemDistrib = [], adaptorList= [], stimList = [], - plotList = [], - moogList = [], + plotList = [], # elecpath, geom_expr, object, field, title ['wave' [min max]] + moogList = [], params = None ): """ Constructor of the rdesigner. This just sets up internal fields @@ -111,6 +115,8 @@ class rdesigneur: self.combineSegments = combineSegments self.stealCellFromLibrary = stealCellFromLibrary self.verbose = verbose + self.addSomaChemCompt = addSomaChemCompt + self.addEndoChemCompt = addEndoChemCompt self.diffusionLength= diffusionLength if meshLambda > 0.0: print("Warning: meshLambda argument is deprecated. Please use 'diffusionLength' instead.\nFor now rdesigneur will accept this argument.") @@ -122,6 +128,7 @@ class rdesigneur: self.elecPlotDt= elecPlotDt self.funcDt= funcDt self.chemPlotDt= chemPlotDt + self.numWaveFrames = numWaveFrames self.cellProtoList = cellProto self.spineProtoList = spineProto @@ -136,17 +143,24 @@ class rdesigneur: self.params = params self.adaptorList = adaptorList - self.stimList = stimList - self.plotList = plotList - self.saveList = plotList #ADDED BY Sarthak + try: + self.stimList = [ rstim.convertArg(i) for i in stimList ] + self.plotList = [ rplot.convertArg(i) for i in plotList ] + self.moogList = [ rmoog.convertArg(i) for i in moogList ] + except BuildError as msg: + print("Error: rdesigneur: " + msg) + quit() + + #self.saveList = plotList #ADDED BY Sarthak self.saveAs = [] - self.moogList = moogList self.plotNames = [] + self.wavePlotNames = [] self.saveNames = [] self.moogNames = [] self.cellPortionElist = [] self.spineComptElist = [] self.tabForXML = [] + self._endos = [] if not moose.exists( '/library' ): library = moose.Neutral( '/library' ) @@ -169,16 +183,10 @@ class rdesigneur: len( self.cellPortionElist ), "compartments.") if hasattr( self , 'chemid' ): dmstoich = moose.element( self.dendCompt.path + '/stoich' ) - print("Chem part of model has ", - self.dendCompt.mesh.num, "dendrite voxels X", - dmstoich.numAllPools, "pools,\n ") - if hasattr( self , 'spineCompt' ): - smstoich = moose.element( self.spineCompt.path + '/stoich') - pmstoich = moose.element( self.psdCompt.path + '/stoich' ) - print(self.spineCompt.mesh.num, "spine voxels X", - smstoich.numAllPools, "pools,", - self.psdCompt.mesh.num, "psd voxels X", - pmstoich.numAllPools, "pools.") + print("Chem part of model has the following compartments: ") + for j in moose.wildcardFind( '/model/chem/##[ISA=ChemCompt]'): + s = moose.element( j.path + '/stoich' ) + print( "In {}, {} voxels X {} pools".format( j.name, j.mesh.num, s.numAllPools ) ) def buildModel( self, modelPath = '/model' ): if moose.exists( modelPath ): @@ -205,7 +213,6 @@ class rdesigneur: self._configureClocks() if self.verbose: self._printModelStats() - self._savePlots() except BuildError as msg: print("Error: rdesigneur: model build failed:", msg) @@ -462,10 +469,10 @@ class rdesigneur: # Here we hack geomExpr to use it for the syn weight. We assume it # is just a number. In due course # it should be possible to actually evaluate it according to geom. - synWeight = float( stimInfo[1] ) + synWeight = float( stimInfo.geom_expr ) stimObj = [] for i in dendCompts + spineCompts: - path = i.path + '/' + stimInfo[2] + '/sh/synapse[0]' + path = i.path + '/' + stimInfo.relpath + '/sh/synapse[0]' if moose.exists( path ): synInput = make_synInput( name='synInput', parent=path ) synInput.doPeriodic = doPeriodic @@ -478,13 +485,17 @@ class rdesigneur: # Here we set up the distributions ################################################################ def buildPassiveDistrib( self ): - # [. path field expr [field expr]...] + # [path field expr [field expr]...] # RM, RA, CM set specific values, per unit area etc. - # Ra, Ra, Cm set absolute values. + # Rm, Ra, Cm set absolute values. # Also does Em, Ek, initVm # Expression can use p, g, L, len, dia, maxP, maxG, maxL. temp = [] for i in self.passiveDistrib: + if (len( i ) < 3) or (len(i) %2 != 1): + raise BuildError( "buildPassiveDistrib: Need 3 + N*2 arguments, have {}".format( len(i) ) ) + + temp.append( '.' ) temp.extend( i ) temp.extend( [""] ) self.elecid.passiveDistribution = temp @@ -605,22 +616,24 @@ class rdesigneur: # [ region_wildcard, region_expr, path, field, title] def _parseComptField( self, comptList, plotSpec, knownFields ): # Put in stuff to go through fields if the target is a chem object - field = plotSpec[3] + field = plotSpec.field if not field in knownFields: print("Warning: Rdesigneur::_parseComptField: Unknown field '{}'".format( field ) ) return (), "" kf = knownFields[field] # Find the field to decide type. if ( kf[0] == 'CaConcBase' or kf[0] == 'ChanBase' or kf[0] == 'NMDAChan' or kf[0] == 'VClamp' ): - objList = self._collapseElistToPathAndClass( comptList, plotSpec[2], kf[0] ) + objList = self._collapseElistToPathAndClass( comptList, plotSpec.relpath, kf[0] ) return objList, kf[1] elif (field == 'n' or field == 'conc' or field == 'volume' ): - path = plotSpec[2] + path = plotSpec.relpath pos = path.find( '/' ) if pos == -1: # Assume it is in the dend compartment. path = 'dend/' + path pos = path.find( '/' ) chemCompt = path[:pos] + if chemCompt[-5:] == "_endo": + chemCompt = chemCompt[0:-5] cc = moose.element( self.modelPath + '/chem/' + chemCompt) voxelVec = [] temp = [ self._makeUniqueNameStr( i ) for i in comptList ] @@ -634,13 +647,13 @@ class rdesigneur: voxelVec = [i for i in range(len( em ) ) if em[i] in comptSet ] # Here we collapse the voxelVec into objects to plot. - allObj = moose.vec( self.modelPath + '/chem/' + plotSpec[2] ) + allObj = moose.vec( self.modelPath + '/chem/' + plotSpec.relpath ) #print "####### allObj=", self.modelPath + '/chem/' + plotSpec[2] if len( allObj ) >= len( voxelVec ): objList = [ allObj[int(j)] for j in voxelVec] else: objList = [] - print( "Warning: Rdesigneur::_parseComptField: unknown Object: '", plotSpec[2], "'" ) + print( "Warning: Rdesigneur::_parseComptField: unknown Object: '", plotSpec.relpath, "'" ) #print "############", chemCompt, len(objList), kf[1] return objList, kf[1] @@ -672,7 +685,7 @@ class rdesigneur: dummy = moose.element( '/' ) k = 0 for i in self.plotList: - pair = i[0] + " " + i[1] + pair = i.elecpath + ' ' + i.geom_expr dendCompts = self.elecid.compartmentsFromExpression[ pair ] spineCompts = self.elecid.spinesFromExpression[ pair ] plotObj, plotField = self._parseComptField( dendCompts, i, knownFields ) @@ -683,15 +696,21 @@ class rdesigneur: #print( "PlotList: {0}: numobj={1}, field ={2}, nd={3}, ns={4}".format( pair, numPlots, plotField, len( dendCompts ), len( spineCompts ) ) ) if numPlots > 0: tabname = graphs.path + '/plot' + str(k) - scale = knownFields[i[3]][2] - units = knownFields[i[3]][3] - self.plotNames.append( ( tabname, i[4], k, scale, units, i[3] ) ) + scale = knownFields[i.field][2] + units = knownFields[i.field][3] + if i.mode == 'wave': + self.wavePlotNames.append( [ tabname, i.title, k, scale, units, i.field, i.ymin, i.ymax ] ) + else: + self.plotNames.append( [ tabname, i.title, k, scale, units, i.field, i.ymin, i.ymax ] ) + if len( i.saveFile ) > 4 and i.saveFile[-4] == '.xml' or i.saveFile: + self.saveNames.append( [ tabname, len(self.saveNames), scale, units, i ] ) + k += 1 - if i[3] == 'n' or i[3] == 'conc' or i[3] == 'volume' or i[3] == 'Gbar': + if i.field == 'n' or i.field == 'conc' or i.field == 'volume' or i.field == 'Gbar': tabs = moose.Table2( tabname, numPlots ) else: tabs = moose.Table( tabname, numPlots ) - if i[3] == 'spikeTime': + if i.field == 'spikeTime': tabs.vec.threshold = -0.02 # Threshold for classifying Vm as a spike. tabs.vec.useSpikeMode = True # spike detect mode on @@ -719,8 +738,8 @@ class rdesigneur: moogliBase = moose.Neutral( self.modelPath + '/moogli' ) k = 0 for i in self.moogList: - kf = knownFields[i[3]] - pair = i[0] + " " + i[1] + kf = knownFields[i.field] + pair = i.elecpath + " " + i.geom_expr dendCompts = self.elecid.compartmentsFromExpression[ pair ] spineCompts = self.elecid.spinesFromExpression[ pair ] dendObj, mooField = self._parseComptField( dendCompts, i, knownFields ) @@ -728,13 +747,6 @@ class rdesigneur: assert( mooField == mooField2 ) mooObj3 = dendObj + spineObj numMoogli = len( mooObj3 ) - #dendComptMap = self.dendCompt.elecComptMap - #self.moogliViewer = rmoogli.makeMoogli( self, mooObj3, mooField ) - if len( i ) == 5: - i.extend( kf[4:6] ) - elif len( i ) == 6: - i.extend( [kf[5]] ) - #self.moogliViewer = rmoogli.makeMoogli( self, mooObj3, i, kf ) self.moogNames.append( rmoogli.makeMoogli( self, mooObj3, i, kf ) ) @@ -757,8 +769,8 @@ rdesigneur.rmoogli.updateMoogliViewer() self.display( len( self.moogNames ) + 1 ) def display( self, startIndex = 0 ): - import matplotlib.pyplot as plt for i in self.plotNames: + # ?, title, fignum, scale, ylabel, wave/spikeTime, ymin, ymax plt.figure( i[2] + startIndex ) plt.title( i[1] ) plt.xlabel( "Time (s)" ) @@ -776,144 +788,79 @@ rdesigneur.rmoogli.updateMoogliViewer() t = np.arange( 0, vtab[0].vector.size, 1 ) * vtab[0].dt for j in vtab: plt.plot( t, j.vector * i[3] ) - if len( self.moogList ) > 0: + if i[6] != i[7]: + plt.ylim( i[6], i[7] ) + if len( self.moogList ) or len( self.wavePlotNames ) > 0: plt.ion() + # Here we build the plots and lines for the waveplots + self.initWavePlots( startIndex ) + if len( self.wavePlotNames ) > 0: + for i in range( 3 ): + self.displayWavePlots() plt.show( block=True ) + self._save() + + + def initWavePlots( self, startIndex ): + self.frameDt = moose.element( '/clock' ).currentTime/self.numWaveFrames + for wpn in range( len(self.wavePlotNames) ): + i = self.wavePlotNames[wpn] + vtab = moose.vec( i[0] ) + if len( vtab ) < 2: + print( "Warning: Waveplot {} abandoned, only {} points".format( i[1], len( vtab ) ) ) + continue + dFrame = len( vtab[0].vector ) / self.numWaveFrames + if dFrame < 1: + dFrame = 1 + vpts = np.array( [ [k.vector[j] for j in range( 0, len( k.vector ), dFrame ) ] for k in vtab] ).T * i[3] + fig = plt.figure( i[2] + startIndex ) + ax = fig.add_subplot( 111 ) + plt.title( i[1] ) + plt.xlabel( "position (voxels)" ) + plt.ylabel( i[4] ) + if i[6] != i[7]: + mn = i[6] + mx = i[7] + else: + mn = np.min(vpts) + mx = np.max(vpts) + if mn/mx < 0.3: + mn = 0 + ax.set_ylim( mn, mx ) + line, = plt.plot( range( len( vtab ) ), vpts[0] ) + timeLabel = plt.text( len(vtab ) * 0.05, mn + 0.9*(mx-mn), 'time = 0' ) + self.wavePlotNames[wpn].append( [fig, line, vpts, timeLabel] ) + fig.canvas.draw() + + def displayWavePlots( self ): + for f in range( self.numWaveFrames ): + for i in self.wavePlotNames: + wp = i[-1] + if len( wp[2] ) > f: + wp[1].set_ydata( wp[2][f] ) + wp[3].set_text( "time = {:.1f}".format(f*self.frameDt) ) + wp[0].canvas.draw() + #plt.pause(0.001) #This calls the _save function which saves only if the filenames have been specified - self._save() ################################################################ # Here we get the time-series data and write to various formats ################################################################ #[TO DO] Add NSDF output function ''' - The author of the functions -- [_savePlots(), _getTimeSeriesTable(), _writeXML(), _writeCSV(), _saveFormats(), _save()] is + The original author of the functions -- [_savePlots(), _writeXML(), _writeCSV(), _save()] is Sarthak Sharma. Email address: sarthaks442@gmail.com + Heavily modified by U.S. Bhalla ''' - - def _savePlots( self ): - - knownFields = { - 'Vm':('CompartmentBase', 'getVm', 1000, 'Memb. Potential (mV)' ), - 'Cm':('CompartmentBase', 'getCm', 1e12, 'Memb. capacitance (pF)' ), - 'Rm':('CompartmentBase', 'getRm', 1e-9, 'Memb. Res (GOhm)' ), - 'Ra':('CompartmentBase', 'getRa', 1e-6, 'Axial Res (MOhm)' ), - 'spikeTime':('CompartmentBase', 'getVm', 1, 'Spike Times (s)'), - 'Im':('CompartmentBase', 'getIm', 1e9, 'Memb. current (nA)' ), - 'inject':('CompartmentBase', 'getInject', 1e9, 'inject current (nA)' ), - 'Gbar':('ChanBase', 'getGbar', 1e9, 'chan max conductance (nS)' ), - 'modulation':('ChanBase', 'getModulation', 1, 'chan modulation (unitless)' ), - 'Gk':('ChanBase', 'getGk', 1e9, 'chan conductance (nS)' ), - 'Ik':('ChanBase', 'getIk', 1e9, 'chan current (nA)' ), - 'ICa':('NMDAChan', 'getICa', 1e9, 'Ca current (nA)' ), - 'Ca':('CaConcBase', 'getCa', 1e3, 'Ca conc (uM)' ), - 'n':('PoolBase', 'getN', 1, '# of molecules'), - 'conc':('PoolBase', 'getConc', 1000, 'Concentration (uM)' ), - 'volume':('PoolBase', 'getVolume', 1e18, 'Volume (um^3)' ), - 'current':('VClamp', 'getCurrent', 1e9, 'Holding Current (nA)') - } - - save_graphs = moose.Neutral( self.modelPath + '/save_graphs' ) - dummy = moose.element( '/' ) - k = 0 - - for i in self.saveList: - pair = i[0] + " " + i[1] - dendCompts = self.elecid.compartmentsFromExpression[ pair ] - spineCompts = self.elecid.spinesFromExpression[ pair ] - plotObj, plotField = self._parseComptField( dendCompts, i, knownFields ) - plotObj2, plotField2 = self._parseComptField( spineCompts, i, knownFields ) - assert( plotField == plotField2 ) - plotObj3 = plotObj + plotObj2 - numPlots = sum( i != dummy for i in plotObj3 ) - if numPlots > 0: - save_tabname = save_graphs.path + '/save_plot' + str(k) - scale = knownFields[i[3]][2] - units = knownFields[i[3]][3] - self.saveNames.append( ( save_tabname, i[4], k, scale, units ) ) - k += 1 - if i[3] == 'n' or i[3] == 'conc' or i[3] == 'volume' or i[3] == 'Gbar': - save_tabs = moose.Table2( save_tabname, numPlots ) - save_vtabs = moose.vec( save_tabs ) - else: - save_tabs = moose.Table( save_tabname, numPlots ) - save_vtabs = moose.vec( save_tabs ) - if i[3] == 'spikeTime': - save_vtabs.threshold = -0.02 # Threshold for classifying Vm as a spike. - save_vtabs.useSpikeMode = True # spike detect mode on - q = 0 - for p in [ x for x in plotObj3 if x != dummy ]: - moose.connect( save_vtabs[q], 'requestOut', p, plotField ) - q += 1 - - def _getTimeSeriesTable( self ): - - ''' - This function gets the list with all the details of the simulation - required for plotting. - This function adds flexibility in terms of the details - we wish to store. - ''' - - knownFields = { - 'Vm':('CompartmentBase', 'getVm', 1000, 'Memb. Potential (mV)' ), - 'spikeTime':('CompartmentBase', 'getVm', 1, 'Spike Times (s)'), - 'Im':('CompartmentBase', 'getIm', 1e9, 'Memb. current (nA)' ), - 'inject':('CompartmentBase', 'getInject', 1e9, 'inject current (nA)' ), - 'Gbar':('ChanBase', 'getGbar', 1e9, 'chan max conductance (nS)' ), - 'Gk':('ChanBase', 'getGk', 1e9, 'chan conductance (nS)' ), - 'Ik':('ChanBase', 'getIk', 1e9, 'chan current (nA)' ), - 'ICa':('NMDAChan', 'getICa', 1e9, 'Ca current (nA)' ), - 'Ca':('CaConcBase', 'getCa', 1e3, 'Ca conc (uM)' ), - 'n':('PoolBase', 'getN', 1, '# of molecules'), - 'conc':('PoolBase', 'getConc', 1000, 'Concentration (uM)' ), - 'volume':('PoolBase', 'getVolume', 1e18, 'Volume (um^3)' ) - } - - ''' - This takes data from plotList - saveList is exactly like plotList but with a few additional arguments: - ->It will have a resolution option, i.e., the number of decimal figures to which the value should be rounded - ->There is a list of "saveAs" formats - With saveList, the user will able to set what all details he wishes to be saved. - ''' - - for i,ind in enumerate(self.saveNames): - pair = self.saveList[i][0] + " " + self.saveList[i][1] - dendCompts = self.elecid.compartmentsFromExpression[ pair ] - spineCompts = self.elecid.spinesFromExpression[ pair ] - # Here we get the object details from plotList - savePlotObj, plotField = self._parseComptField( dendCompts, self.saveList[i], knownFields ) - savePlotObj2, plotField2 = self._parseComptField( spineCompts, self.saveList[i], knownFields ) - savePlotObj3 = savePlotObj + savePlotObj2 - - rowList = list(ind) - save_vtab = moose.vec( ind[0] ) - t = np.arange( 0, save_vtab[0].vector.size, 1 ) * save_vtab[0].dt - - rowList.append(save_vtab[0].dt) - rowList.append(t) - rowList.append([jvec.vector * ind[3] for jvec in save_vtab]) #get values - rowList.append(self.saveList[i][3]) - rowList.append(filter(lambda obj: obj.path != '/', savePlotObj3)) #this filters out dummy elements - - if (type(self.saveList[i][-1])==int): - rowList.append(self.saveList[i][-1]) - else: - rowList.append(12) - - self.tabForXML.append(rowList) - rowList = [] - - timeSeriesTable = self.tabForXML # the list with all the details of plot - return timeSeriesTable - - def _writeXML( self, filename, timeSeriesData ): #to write to XML file - - plotData = timeSeriesData - print("[CAUTION] The '%s' file might be very large if all the compartments are to be saved." % filename) + def _writeXML( self, plotData, time, vtab ): + tabname = plotData[0] + idx = plotData[1] + scale = plotData[2] + units = plotData[3] + rp = plotData[4] + filename = rp.saveFile[:-4] + str(idx) + '.xml' root = etree.Element("TimeSeriesPlot") parameters = etree.SubElement( root, "parameters" ) if self.params == None: @@ -926,81 +873,59 @@ rdesigneur.rmoogli.updateMoogliViewer() #plotData contains all the details of a single plot title = etree.SubElement( root, "timeSeries" ) - title.set( 'title', str(plotData[1])) - title.set( 'field', str(plotData[8])) - title.set( 'scale', str(plotData[3])) - title.set( 'units', str(plotData[4])) - title.set( 'dt', str(plotData[5])) + title.set( 'title', rp.title) + title.set( 'field', rp.field) + title.set( 'scale', str(scale) ) + title.set( 'units', units) + title.set( 'dt', str(vtab[0].dt) ) + res = rp.saveResolution p = [] - assert(len(plotData[7]) == len(plotData[9])) - - res = plotData[10] - for ind, jvec in enumerate(plotData[7]): + for t, v in zip( time, vtab ): p.append( etree.SubElement( title, "data")) - p[-1].set( 'path', str(plotData[9][ind].path)) - p[-1].text = ''.join( str(round(value,res)) + ' ' for value in jvec ) - + p[-1].set( 'path', v.path ) + p[-1].text = ''.join( str(round(y,res)) + ' ' for y in v.vector ) tree = etree.ElementTree(root) tree.write(filename) - def _writeCSV(self, filename, timeSeriesData): - - plotData = timeSeriesData - dataList = [] - header = [] - time = plotData[6] - res = plotData[10] - - for ind, jvec in enumerate(plotData[7]): - header.append(plotData[9][ind].path) - dataList.append([round(value,res) for value in jvec.tolist()]) - dl = [tuple(lst) for lst in dataList] - rows = zip(tuple(time), *dl) - header.insert(0, "time") - + def _writeCSV( self, plotData, time, vtab ): + tabname = plotData[0] + idx = plotData[1] + scale = plotData[2] + units = plotData[3] + rp = plotData[4] + filename = rp.saveFile[:-4] + str(idx) + '.csv' + + header = ["time",] + valMatrix = [time,] + header.extend( [ v.path for v in vtab ] ) + valMatrix.extend( [ v.vector for v in vtab ] ) + nv = np.array( valMatrix ).T with open(filename, 'wb') as f: writer = csv.writer(f, quoting=csv.QUOTE_MINIMAL) writer.writerow(header) - for row in rows: + for row in nv: writer.writerow(row) ##########****SAVING*****############### - def _saveFormats(self, timeSeriesData, k, *filenames): - "This takes in the filenames and writes to corresponding format." - if filenames: - for filename in filenames: - for name in filename: - print (name) - if name[-4:] == '.xml': - self._writeXML(name, timeSeriesData) - print(name, " written") - elif name[-4:] == '.csv': - self._writeCSV(name, timeSeriesData) - print(name, " written") - else: - print("not possible") - pass - else: - pass def _save( self ): - timeSeriesTable = self._getTimeSeriesTable() - for i,sList in enumerate(self.saveList): - - if (len(sList) >= 6) and (type(sList[5]) != int): - self.saveAs.extend(filter(lambda fmt: type(fmt)!=int, sList[5:])) - try: - timeSeriesData = timeSeriesTable[i] - except IndexError: - print("The object to be plotted has all dummy elements.") - pass - self._saveFormats(timeSeriesData, i, self.saveAs) - self.saveAs=[] + for i in self.saveNames: + tabname = i[0] + idx = i[1] + scale = i[2] + units = i[3] + rp = i[4] # The rplot data structure, it has the setup info. + + vtab = moose.vec( tabname ) + t = np.arange( 0, vtab[0].vector.size, 1 ) * vtab[0].dt + ftype = rp.filename[-4:] + if ftype == '.xml': + self._writeXML( i, t, vtab ) + elif ftype == '.csv': + self._writeCSV( i, t, vtab ) else: - pass - else: - pass + print("Save format '{}' not known, please use .csv or .xml".format( ftype ) ) ################################################################ # Here we set up the stims @@ -1008,9 +933,11 @@ rdesigneur.rmoogli.updateMoogliViewer() def _buildStims( self ): knownFields = { 'inject':('CompartmentBase', 'setInject'), - 'Ca':('CaConcBase', 'getCa'), + 'Ca':('CaConcBase', 'setCa'), 'n':('PoolBase', 'setN'), 'conc':('PoolBase', 'setConc'), + 'nInit':('PoolBase', 'setNinit'), + 'concInit':('PoolBase', 'setConcInit'), 'vclamp':('CompartmentBase', 'setInject'), 'randsyn':('SynChan', 'addSpike'), 'periodicsyn':('SynChan', 'addSpike') @@ -1019,17 +946,17 @@ rdesigneur.rmoogli.updateMoogliViewer() k = 0 # Stimlist = [path, geomExpr, relPath, field, expr_string] for i in self.stimList: - pair = i[0] + " " + i[1] + pair = i.elecpath + " " + i.geom_expr dendCompts = self.elecid.compartmentsFromExpression[ pair ] spineCompts = self.elecid.spinesFromExpression[ pair ] #print( "pair = {}, numcompts = {},{} ".format( pair, len( dendCompts), len( spineCompts ) ) ) - if i[3] == 'vclamp': + if i.field == 'vclamp': stimObj3 = self._buildVclampOnCompt( dendCompts, spineCompts, i ) stimField = 'commandIn' - elif i[3] == 'randsyn': + elif i.field == 'randsyn': stimObj3 = self._buildSynInputOnCompt( dendCompts, spineCompts, i ) stimField = 'setRate' - elif i[3] == 'periodicsyn': + elif i.field == 'periodicsyn': stimObj3 = self._buildSynInputOnCompt( dendCompts, spineCompts, i, doPeriodic = True ) stimField = 'setRate' else: @@ -1042,9 +969,9 @@ rdesigneur.rmoogli.updateMoogliViewer() funcname = stims.path + '/stim' + str(k) k += 1 func = moose.Function( funcname ) - func.expr = i[4] - if i[3] == 'vclamp': # Hack to clean up initial condition - func.doEvalAtReinit = 1 + func.expr = i.expr + #if i[3] == 'vclamp': # Hack to clean up initial condition + func.doEvalAtReinit = 1 for q in stimObj3: moose.connect( func, 'valueOut', q, stimField ) @@ -1267,6 +1194,7 @@ rdesigneur.rmoogli.updateMoogliViewer() if len( comptlist ) == 0: raise BuildError( "validateChem: no compartment on: " + cpath ) + ''' if len( comptlist ) == 1: return; @@ -1276,6 +1204,7 @@ rdesigneur.rmoogli.updateMoogliViewer() print(cpath, sortedComptlist) raise BuildError( "validateChem: Require 3 chem compartments, have: " + str( len( sortedComptlist ) ) ) ''' + ''' if not( sortedComptlist[0].name.lower() == 'dend' and \ sortedComptlist[1].name.lower() == 'spine' and \ sortedComptlist[2].name.lower() == 'psd' ): @@ -1287,38 +1216,115 @@ rdesigneur.rmoogli.updateMoogliViewer() ################################################################# + def _isModelFromKkit( self ): + for i in self.chemProtoList: + if i[0][-2:] == ".g": + return True + return False + + def _assignComptNamesFromKkit( self ): + ''' + Algorithm: Identify compts by volume. Assume a couple of standard + orders depending on the addSomaChemCompt and addEndoChemCompt + flags:\n + ascc = 0, aecc = 0: dend, spine, psd.\n + ascc = 0, aecc = 1: dend, dend_endo, spine, spine_endo, psd, psd_endo.\n + ascc = 1, aecc = 0: soma, dend, spine, psd.\n + ascc = 1, aecc = 1: soma, soma_endo, dend, dend_endo, spine, spine_endo, psd, psd_endo.\n + In all cases, a shorter list of chem compartments will only fill + up the list to the available length.\n + soma_endo can be thought of as nucleus.\n + psd_endo doesn't really make sense, as peri-synaptic region really + needs to talk both to PSD and to spine bulk. + ''' + comptList = moose.wildcardFind( self.chemid.path + '/#[ISA=ChemCompt]' ) + #print( "comptList = {}".format ( [i.name for i in comptList]) ) + if len( comptList ) < 2: + if comptList[0].name != 'dend': + comptList[0].name = 'dend' + return comptList + if not self._isModelFromKkit(): + print( "Not isModelfromKkit" ) + return comptList + sortedComptList = sorted( comptList, key=lambda x: -x.volume ) + if self.addSomaChemCompt: + if self.addEndoChemCompt: + sortedNames = ["soma", "soma_endo", "dend", "dend_endo", "spine", "spine_endo", "psd", "psd_endo", ] + else: + sortedNames = ["soma", "dend", "spine","psd"] + else: + if self.addEndoChemCompt: + sortedNames = ["dend", "dend_endo", "spine", "spine_endo", "psd", "psd_endo", ] + else: + sortedNames = ["dend", "spine","psd"] + + #print( "sortedNames = {}".format( sortedNames ) ) + for i in range(min( len( sortedComptList ), len( sortedNames ) ) ): + #print( "SortedClist= {}".format( sortedComptList[i] )) + if sortedComptList[i].name != sortedNames[i]: + sortedComptList[i].name = sortedNames[i] + return sortedComptList + + def _buildNeuroMesh( self ): - comptlist = moose.wildcardFind( self.chemid.path + '/#[ISA=ChemCompt]' ) - sortedComptList = sorted( comptlist, key=lambda x: -x.volume ) - # A little juggling here to put the chem pathways onto new meshes. + # Address the following cases: + # - dend alone + # - dend with spine and PSD + # - above plus n endo meshes located as per name suffix: + # er_1_dend, vesicle_2_spine, + # - above plus presyn, e.g.: + # er_1_dend, vesicle_2_spine, + # - above plus soma + # - soma alone + # - soma plus n endo meshes + self.chemid.name = 'temp_chem' newChemid = moose.Neutral( self.model.path + '/chem' ) - self.dendCompt = moose.NeuroMesh( newChemid.path + '/dend' ) - self.dendCompt.geometryPolicy = 'cylinder' - self.dendCompt.separateSpines = 0 - if len( sortedComptList ) == 3: + comptlist = self._assignComptNamesFromKkit() + comptdict = { i.name:i for i in comptlist } + if len(comptdict) == 1 or 'dend' in comptdict: + self.dendCompt = moose.NeuroMesh( newChemid.path + '/dend' ) + self.dendCompt.geometryPolicy = 'cylinder' + self.dendCompt.separateSpines = 0 + self._moveCompt( comptdict['dend'], self.dendCompt ) + comptdict['dend'] = self.dendCompt + + if 'dend' in comptdict and 'spine' in comptdict: + #print( "comptdict = {}".format (comptdict ) ) self.dendCompt.separateSpines = 1 self.spineCompt = moose.SpineMesh( newChemid.path + '/spine' ) moose.connect( self.dendCompt, 'spineListOut', self.spineCompt, 'spineList' ) + self._moveCompt( comptdict['spine'], self.spineCompt ) + comptdict['spine'] = self.spineCompt + # We need to make a PSD in the spine even if it is uninhabited. self.psdCompt = moose.PsdMesh( newChemid.path + '/psd' ) moose.connect( self.dendCompt, 'psdListOut', self.psdCompt, 'psdList','OneToOne') - #Move the old reac systems onto the new compartments. - self._moveCompt( sortedComptList[0], self.dendCompt ) - if len( sortedComptList ) == 3: - self._moveCompt( sortedComptList[1], self.spineCompt ) - self._moveCompt( sortedComptList[2], self.psdCompt ) + if 'psd' in comptdict: # Shift stuff over if any. + self._moveCompt( comptdict['psd'], self.psdCompt ) + comptdict['psd'] = self.psdCompt + self.dendCompt.diffLength = self.diffusionLength self.dendCompt.subTree = self.cellPortionElist + for i in comptdict: + if len(i) > 5: + if i[-5:] == '_endo': + endo = moose.EndoMesh( newChemid.path + '/' +i ) + surround = comptdict[i[0:-5]] + self._endos.append( [endo, surround] ) + #print( "{}****{}".format(i[0:-5], comptdict[i[0:-5]])) + self._moveCompt( comptdict[i], endo ) + comptdict[i] = endo moose.delete( self.chemid ) self.chemid = newChemid + ################################################################# def _configureSolvers( self ) : if not hasattr( self, 'chemid' ): return if not hasattr( self, 'dendCompt' ): raise BuildError( "configureSolvers: no chem meshes defined." ) - fixXreacs.fixXreacs( self.chemid.path ) + fixXreacs( self.chemid.path ) dmksolve = moose.Ksolve( self.dendCompt.path + '/ksolve' ) dmdsolve = moose.Dsolve( self.dendCompt.path + '/dsolve' ) dmstoich = moose.Stoich( self.dendCompt.path + '/stoich' ) @@ -1349,6 +1355,8 @@ rdesigneur.rmoogli.updateMoogliViewer() pmstoich.compartment = self.psdCompt pmstoich.ksolve = pmksolve pmstoich.dsolve = pmdsolve + if len( moose.wildcardFind( 'self.psdCompt.path/##[ISA=PoolBase]' ) ) == 0: + moose.Pool( self.psdCompt.path + '/dummy' ) pmstoich.path = self.psdCompt.path + "/##" # Here we should test what kind of geom we have to use @@ -1359,6 +1367,23 @@ rdesigneur.rmoogli.updateMoogliViewer() # set up the connections so that the spine volume scaling can happen self.elecid.setSpineAndPsdMesh( self.spineCompt, self.psdCompt) self.elecid.setSpineAndPsdDsolve( smdsolve, pmdsolve ) + for i in self._endos: + i[0].isMembraneBound = True + i[0].surround = i[1] + #i[0].elecComptMap = i[1].elecComptMap + path = i[0].path + #print( "Doing endo {} inside {}".format( path, i[1].path ) ) + if self.useGssa: + eksolve = moose.Gsolve( path + '/ksolve' ) + else: + eksolve = moose.Ksolve( path + '/ksolve' ) + edsolve = moose.Dsolve( path + '/dsolve' ) + estoich = moose.Stoich( path + '/stoich' ) + estoich.compartment = i[0] + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = path + "/##" + edsolve.buildMeshJunctions( moose.element(i[1].path + '/dsolve' )) ################################################################ def _loadChem( self, fname, chemName ): @@ -1369,6 +1394,7 @@ rdesigneur.rmoogli.updateMoogliViewer() print("loadChem: No compartment found in file: ", fname) return # Sort comptlist in decreasing order of volume + ''' sortedComptlist = sorted( comptlist, key=lambda x: -x.volume ) if ( len( sortedComptlist ) >= 1 ): sortedComptlist[0].name = 'dend' @@ -1376,6 +1402,7 @@ rdesigneur.rmoogli.updateMoogliViewer() sortedComptlist[1].name = 'spine' if ( len( sortedComptlist ) >= 3 ): sortedComptlist[2].name = 'psd' + ''' ################################################################ @@ -1384,6 +1411,7 @@ rdesigneur.rmoogli.updateMoogliViewer() for i in moose.wildcardFind( a.path + '/#' ): if ( i.name != 'mesh' ): moose.move( i, b ) + #print( "Moving {} {} to {}".format( i.className, i.name, b.name )) moose.delete( a ) ################################################################ def _buildAdaptor( self, meshName, elecRelPath, elecField, \ @@ -1458,3 +1486,94 @@ rdesigneur.rmoogli.updateMoogliViewer() moose.connect( i[3], 'requestOut', chemVec[j], chemFieldSrc) msg = moose.connect( i[3], 'output', elObj, elecFieldDest ) + +####################################################################### +# Some helper classes, used to define argument lists. +####################################################################### + +class baseplot: + def __init__( self, + elecpath='soma', geom_expr='1', relpath='.', field='Vm' ): + self.elecpath = elecpath + self.geom_expr = geom_expr + self.relpath = relpath + self.field = field + +class rplot( baseplot ): + def __init__( self, + elecpath = 'soma', geom_expr = '1', relpath = '.', field = 'Vm', + title = 'Membrane potential', + mode = 'time', + ymin = 0.0, ymax = 0.0, + saveFile = "", saveResolution = 3, show = True ): + baseplot.__init__( self, elecpath, geom_expr, relpath, field ) + self.title = title + self.mode = mode # Options: time, wave, wave_still, raster + self.ymin = ymin # If ymin == ymax, it autoscales. + self.ymax = ymax + if len( saveFile ) < 5: + self.saveFile = "" + else: + f = saveFile.split('.') + if len(f) < 2 or ( f[-1] != 'xml' and f[-1] != 'csv' ): + raise BuildError( "rplot: Filetype is '{}', must be of type .xml or .csv.".format( f[-1] ) ) + self.saveFile = saveFile + self.show = show + + def printme( self ): + print( "{}, {}, {}, {}, {}, {}, {}, {}, {}, {}".format( + self.elecpath, + self.geom_expr, self.relpath, self.field, self.title, + self.mode, self.ymin, self.ymax, self.saveFile, self.show ) ) + + @staticmethod + def convertArg( arg ): + if isinstance( arg, rplot ): + return arg + elif isinstance( arg, list ): + return rplot( *arg ) + else: + raise BuildError( "rplot initialization failed" ) + +class rmoog( baseplot ): + def __init__( self, + elecpath = 'soma', geom_expr = '1', relpath = '.', field = 'Vm', + title = 'Membrane potential', + ymin = 0.0, ymax = 0.0, + show = True ): # Could put in other display options. + baseplot.__init__( self, elecpath, geom_expr, relpath, field ) + self.title = title + self.ymin = ymin # If ymin == ymax, it autoscales. + self.ymax = ymax + self.show = show + + @staticmethod + def convertArg( arg ): + if isinstance( arg, rmoog ): + return arg + elif isinstance( arg, list ): + return rmoog( *arg ) + else: + raise BuildError( "rmoog initialization failed" ) + + # Stimlist = [path, geomExpr, relPath, field, expr_string] +class rstim( baseplot ): + def __init__( self, + elecpath = 'soma', geom_expr = '1', relpath = '.', field = 'inject', expr = '0'): + baseplot.__init__( self, elecpath, geom_expr, relpath, field ) + self.expr = expr + + def printme( self ): + print( "{}, {}, {}, {}, {}, {}, {}, {}, {}, {}".format( + self.elecpath, + self.geom_expr, self.relpath, self.field, self.expr ) ) + + @staticmethod + def convertArg( arg ): + if isinstance( arg, rstim ): + return arg + elif isinstance( arg, list ): + return rstim( *arg ) + else: + raise BuildError( "rstim initialization failed" ) + diff --git a/moose-core/python/rdesigneur/rdesigneurProtos.py b/moose-core/python/rdesigneur/rdesigneurProtos.py index ec5d705936d16a3fe624afa12dead0f83dc99e7d..920caabaa6ce0a2eb8c1717f19b019e69006fd60 100644 --- a/moose-core/python/rdesigneur/rdesigneurProtos.py +++ b/moose-core/python/rdesigneur/rdesigneurProtos.py @@ -757,8 +757,8 @@ def makePassiveHHsoma(name = 'passiveHHsoma', parent='/library'): if not moose.exists( elecpath ): elecid = moose.Neuron( elecpath ) dia = 500e-6 - soma = buildComptWrapper( elecid, 'soma', dia, dia, 0.0, - 0.33333333, 3000, 0.01 ) + soma = buildCompt( elecid, 'soma', dx = dia, dia = dia, x = 0.0, + RM = 0.33333333, RA = 3000, CM = 0.01 ) soma.initVm = -65e-3 # Resting of -65, from HH soma.Em = -54.4e-3 # 10.6 mV above resting of -65, from HH else: diff --git a/moose-core/python/rdesigneur/rmoogli.py b/moose-core/python/rdesigneur/rmoogli.py index f98549c0b2f9b4109774da64d57a68ebbb9396a5..16317b5686aca2abb90e58faad963dcd17b21061 100644 --- a/moose-core/python/rdesigneur/rmoogli.py +++ b/moose-core/python/rdesigneur/rmoogli.py @@ -20,21 +20,29 @@ def makeMoogli( rd, mooObj, args, fieldInfo ): # Cleaner still would be to have the C code give a vector of values # For now it means something different for chem and elec displays. #moogliEntry = [elecPath,bool,whichObjToDisplay,FieldToDisplay,titleForDisplay,rangeMin,rangeMax] - mooField = args[3] - relObjPath = args[2] + mooField = args.field + relObjPath = args.relpath numMoogli = len( mooObj ) + if args.ymin != args.ymax: + ymin = args.ymin + ymax = args.ymax + else: + ymin = fieldInfo[4] + ymax = fieldInfo[5] + print( "fieldinfo = {}, ymin = {}, ymax = {}".format( fieldInfo, ymin, ymax )) viewer = moogul.MooView() if mooField == 'n' or mooField == 'conc': #moogul.updateDiffCoords( mooObj ) reacSystem = moogul.MooReacSystem( mooObj, fieldInfo, field = mooField, relativeObj = relObjPath, - valMin = args[5], valMax = args[6] ) + valMin = ymin, valMax = ymax ) viewer.addDrawable( reacSystem ) else: neuron = moogul.MooNeuron( rd.elecid, fieldInfo, field = mooField, relativeObj = relObjPath, - valMin = args[5], valMax = args[6] ) + valMin = ymin, valMax = ymax ) + print( "min = {}, max = {}".format(ymin, ymax) ) viewer.addDrawable( neuron ) return viewer diff --git a/moose-core/randnum/Binomial.cpp b/moose-core/randnum/Binomial.cpp deleted file mode 100644 index 2014c283cd19ff846e883e71e2940f386ec7dfac..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Binomial.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/******************************************************************* - * File: Binomial.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-10-28 13:44:46 - ********************************************************************/ -/********************************************************************** - ** This program is part of 'MOOSE', the - ** Messaging Object Oriented Simulation Environment, - ** also known as GENESIS 3 base code. - ** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS - ** It is made available under the terms of the - ** GNU General Public License version 2 - ** See the file COPYING.LIB for the full notice. - **********************************************************************/ - -#ifndef _BINOMIAL_CPP -#define _BINOMIAL_CPP -#include <cmath> -#include "randnum.h" -#include "utility/numutil.h" -#include "Binomial.h" -#include <vector> -#include <iostream> -#include <climits> -using namespace std; - -// First 10 entries in lookup table -const double fc[] = { - 0.08106146679532726, - 0.04134069595540929, - 0.02767792568499834, - 0.02079067210376509, - 0.01664469118982119, - 0.01387612882307075, - 0.01189670994589177, - 0.01041126526197209, - 0.009255462182712733, - 0.008330563433362871 -}; - - -/// Insert first 100 elements in lookup table -const vector <double> initializeLookupTable() -{ - static vector <double> table; - - for ( int i = 0; i < 10; ++i ) - { - table.push_back(fc[i]); - } - for ( int i = 10; i < 100; ++i ) - { - double denom = 1.0/(i+1); - double value = (0.083333333333333333 - (0.002777777777777778 - 0.0007936508*denom*denom)*denom*denom)*denom; - table.push_back(value); - } - return table; -} -static const vector <double> lookupTable = initializeLookupTable(); - - - -/** - retrieve fc value from table or calculate it depending on the value of k -*/ -inline double getFc(unsigned int k) -{ - if (lookupTable.size() <= k ) - { - double denom = 1.0/(k+1); - return (0.083333333333333333 - (0.002777777777777778 - 0.0007936508*denom*denom)*denom*denom)*denom; - } - else - { - return lookupTable[k]; - } -} - -/** - Binomial distribution generator with parameters n and p. p is the - probability of the favoured outcome, n is the number of trials. - */ -Binomial::Binomial( long n, double p):n_(n), p_(p) -{ - - if (( p < 0 ) || ( p > 1 )) - { - cerr << "ERROR: p must be in [0,1] range." << endl; - p = 0.0; - return; - } - if ( n < 1 ) - { - cerr << "ERROR: n must be >= 1" << endl; - return; - } - - - double tmpMean; - double tmp; - isInverted_ = false; - -// tmpMean = n*((p < 0.5)? p : (1-p)); - -// if ((tmpMean > 10.0)) -// { - // the above can be simplified as: ( saves one floating point comparison, aesthetically pleasing :D ) - if ( n > 20 ) - { - if( p < 0.5 ) - { - p_ = p; - } - else - { - p_ = 1.0 - p; - isInverted_ = true; - } - tmpMean = n*p_; - - tmp = sqrt(tmpMean*(1.0 - p_)); - paramC_ = tmpMean + 0.5; - paramB_ = 1.15 + 2.53*tmp; - paramA_ = -0.0873 + 0.0248*paramB_ + 0.01*p_; - paramAlpha_ = (2.83 + 5.1/paramB_)*tmp; - paramUr_ = 0.43; - paramVr_ = 0.92 - 4.2/paramB_; - paramUrVr_ = 0.86*paramVr_; - paramM_ = floor(tmpMean+p_); - paramR_ = floor(p_/(1-p_)); - paramNr_ = (n+1)*paramR_; - paramNpq_ = tmpMean*(1-p_); - } - mean_ = n_*p_; -} - -long Binomial::getN() const -{ - return n_; -} - -double Binomial::getP() const -{ - if ( isInverted_) - { - return 1 - p_; - } - else - { - return p_; - } -} - -double Binomial::getMean() const -{ - if (isInverted_) - { - return (n_ - mean_); - }else{ - return mean_; - } -} - -double Binomial::getVariance() const -{ - static double variance = sqrt(n_*p_*(1.0-p_)); - return variance; -} - -/** - returns the next random number in this distribution as the ratio of - the number of positive outcomes and the total number of trials. - This is the most naive implementation. This is ok for small n. - For large n such that mean > 10, we use BTRD algorithm by Hoermann. - See documentation of generateTrd() for further detail. -*/ -double Binomial::getNextSample() const -{ - double sample = 0; - if ( p_ == 0 ) - { - sample = (double)0; - } - else if ( isClose<double>(1.0,p_, DBL_EPSILON)) - { - sample = (double)n_; - } - else - { - if ( mean_ > 10 ) - { - sample = isInverted_? n_ - generateTrd(): generateTrd(); - } - else - { - for ( unsigned int i = 0; i < n_; ++i) - { - double myRand = mtrand(); - if ( myRand < p_ ) - { - sample+=1; - } - } - } -// cerr << "Sample value: " << sample << " " << isInverted_<< endl; - } - - return sample; -} - -/** - Generate binomially distributed random numbers using transformed - rejection with decomposition as described in "The Generation of - Binomial Random Variable" by W Hoermann. -*/ -double Binomial::generateTrd() const -{ - - double varV; - double varU; - double varUs; - double varK; - double varKm; - double varF; - double varNm; - double varH; - double varNk; - double varI; - double varRho; - double varT; - - while ( true ) - { - // 1a: generate a uniform random number v - varV = mtrand(); - if ( varV <= paramUrVr_ ) - { - // 1b: if v <= urvr then u = v/vr - 0.43 - double varU = varV/paramVr_ - 0.43; - // 1c: return floor( (2*a/(0.5 - |u|) + b ) * u + c ) - return floor((2*paramA_/(0.5 - fabs(varU)) + paramB_ )*varU+paramC_); - } - // 2a: if ( v >= vr ) then generate a uniform random number u in (-0.5,+0.5) - if ( varV >= paramVr_ ) - { - varU = mtrand() - 0.5; - } - else // 2b: otherwise - { - // 2b(i): set u = v/vr - 0.93 - varU = varV/paramVr_ - 0.93; - // 2b(ii): set u = sign(u)*0.5 - u - varU = (varU > 0)? 0.5 - varU : - 0.5 - varU; - // 2b(iii) generate a uniform random number v in (0,vr) - varV = mtrand()*paramVr_; - } - // 3.0a: us = 0.5 - |u| - varUs = (varU < 0) ? 0.5 + varU : 0.5 - varU; - // 3.0b: k = floor( ( 2*a/us + b )*u + c ) - varK = floor( (2*paramA_/varUs+paramB_)*varU + paramC_); - // 3.0c: if k < 0 or k > n go to (1) - if ( (varK < 0) || ( varK > n_ )) - { - continue; - } - - // 3.0d: v = v*alpha/(a/(us*us)+b) - varV = varV*paramAlpha_/(paramA_/(varUs*varUs) + paramB_ ); - // 3.0e: km = | k - m | - varKm = ( varK < paramM_)? paramM_ - varK : varK - paramM_; - // 3.0f: if km > 15 go to 3.2 , else ... - if ( varKm <= 15 ) - { - // 3.1: recursive evaluation of f(k) - // 3.1a: f = 1 - varF = 1; - // 3.1b: if (m < k) - if ( paramM_ < varK ) - { - // 3.1b(i): set i = m - varI = paramM_; - // 3.1b(ii): repeat i = i+1, f = f*(nr/i - r) until (i == k). - while ( varI < varK ) - { - ++varI; - varF *= (paramNr_/varI - paramR_); - } - } - else // 3.1c: otherwise ... - { - // 3.1c(i) if ( m > k) - if ( paramM_ > varK ) - { - // 3.1c(ii): i = k - varI = varK; - // 3.1c(ii): repeat i = i+1, v = v*(nr/i - r) until (i == m). - while ( varI < paramM_) - { - ++varI; - varV *= (paramNr_/varI -paramR_); - } - } - //3.1d: if v <= f return k, otherwise goto (1) - if ( varV <= varF ) - { - return varK; - } - } - } - // 3.2: Squeeze acceptance or rejection - // 3.2a: v = log(v) - varV = log(varV); - // 3.2b: rho = ( km/npq )*(((km/3+0.625)*km + 1/6)/npq+0.5) - varRho = (varKm/paramNpq_)*(((varKm/3.0+ 0.625)*varKm+0.16666666666666667)/paramNpq_+0.5); - // 3.2c: t = - km*km/(2*npq) - varT = -varKm*varKm*0.5/paramNpq_; - // 3.2d: if ( v < t - rho ) then return k - if ( varV < ( varT - varRho )) - { - return varK; - } - // 3.2e: if ( v > t+rho ) then goto (1) - if ( varV > (varT + varRho)) - { - continue; - } - // 3.3: Set-up for 3.4 - // 3.3a: nm = n - m + 1 - varNm = n_ - paramM_ + 1; - // 3.3b: h = (m+0.5)*log((m+1)/(r*nm)) + fc(m) + fc(n-m) - varH = (paramM_ + 0.5)*log((paramM_+1)/(paramR_*varNm)) + getFc((int)paramM_) + getFc((int)(n_-paramM_)); - // 3.4: Final acceptance-rejection test - // 3.4a: nk = n - k + 1; - varNk = n_ - varK + 1; - // 3.4b: if ( v <= h + (n+1)*log(nm/nk) + (k+0.5)*log(nk*r/(k+1)) - fc(k) -fc(n-k) then return k - if ( varV <= varH + (n_ + 1)*log(varNm/varNk) + ( varK + 0.5)*log(varNk*paramR_/(varK+1)) - getFc((int)varK) - getFc((int)(n_ - varK))) - { - return varK; - } - // 3.4c: otherwise goto (1) - } -} - - -/** - TODO: what to do to automatically test the quality of the random - number generation? We can check the mean and variance perhaps? - We should also check the plot of the distribution manually. -*/ -void testBinomial() -{ - - int trialMin = 2; - int trialMax = trialMin*1000; - - double tmp; - - - for ( int i = trialMin; i < trialMax; i =(int)( i* 1.5) ) - { - for ( double p = 0.1; p < .95; p += 0.1) - { - Binomial b(i, p); - tmp = 0; - for ( int j = 0; j < i; ++j ) - { - tmp += b.getNextSample(); - } - cerr << "Diff( " << i << "," << p << ") " - << tmp/i - b.getMean() - << " [ " << tmp/i << " - " << b.getMean() <<" ]" - << endl; - } - } -} -#if 0 // test main -int main(void) -{ - testBinomial(); - return 0; -} - -#endif // test main - - -#endif diff --git a/moose-core/randnum/Binomial.h b/moose-core/randnum/Binomial.h deleted file mode 100644 index 06401f4d32061bea9b68d11955572e79f04bb423..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Binomial.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************* - * File: Binomial.h - * Description: Implements binomial distribution - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-10-28 13:42:24 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _BINOMIAL_H -#define _BINOMIAL_H -#include "Probability.h" - -class Binomial:public Probability -{ - public: - Binomial(){}; - Binomial( long n, double p); - long getN() const; - double getP() const; - double getMean() const; - double getVariance() const; - double getNextSample() const; - - private: - double generateTrd() const; - bool isInverted_; - - unsigned long n_; - double p_; - double mean_; - - double paramC_; - double paramB_; - double paramA_; - double paramAlpha_; - double paramUr_; - double paramVr_; - double paramUrVr_; - double paramM_; - double paramR_; - double paramNr_; - double paramNpq_; -}; - - -#endif diff --git a/moose-core/randnum/BinomialRng.cpp b/moose-core/randnum/BinomialRng.cpp deleted file mode 100644 index 50765b2e0b2e6edf0ed37a9dbc5e1b8aeb215e0a..0000000000000000000000000000000000000000 --- a/moose-core/randnum/BinomialRng.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/******************************************************************* - * File: BinomialRng.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 10:58:01 - ********************************************************************/ -/********************************************************************** - ** This program is part of 'MOOSE', the - ** Messaging Object Oriented Simulation Environment, - ** also known as GENESIS 3 base code. - ** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS - ** It is made available under the terms of the - ** GNU General Public License version 2 - ** See the file COPYING.LIB for the full notice. - **********************************************************************/ - -#ifndef _BINOMIALRNG_CPP -#define _BINOMIALRNG_CPP -#include "BinomialRng.h" -#include "Binomial.h" -#include "utility/numutil.h" -#include <cmath> -extern const Cinfo* initRandGeneratorCinfo(); - -const Cinfo* BinomialRng::initCinfo() -{ - static ValueFinfo< BinomialRng, double > n( - "n", - "Parameter n of the binomial distribution. In a coin toss experiment," - " this is the number of tosses.", - &BinomialRng::setN, - &BinomialRng::getN); - static ValueFinfo < BinomialRng, double > p( - "p", - "Parameter p of the binomial distribution. In a coin toss experiment," -" this is the probability of one of the two sides of the coin being on" -" top.", - &BinomialRng::setP, - &BinomialRng::getP); - static Finfo* binomialRngFinfos[] = { - &n, - &p, - }; - - static string doc[] = { - "Name", "BinomialRng", - "Author", "Subhasis Ray", - "Description", "Binomially distributed random number generator.", - }; - Dinfo < BinomialRng> dinfo; - static Cinfo binomialRngCinfo( - "BinomialRng", - RandGenerator::initCinfo(), - binomialRngFinfos, - sizeof(binomialRngFinfos)/sizeof(Finfo*), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - return &binomialRngCinfo; -} - - -static const Cinfo* binomialRngCinfo = BinomialRng::initCinfo(); - -BinomialRng::BinomialRng() -{ - isNSet_ = false; - isPSet_ = false; - isModified_ = true; - - n_ = 0; - p_ = 0; -} - -/** - Set parameter n ( number of trials for a two-outcome experiment). - This must be set before the actual generator is instantiated. - */ -void BinomialRng::setN(double value) -{ - unsigned long n = (unsigned long)value; - if ( n <= 0 ) - { - cerr << "ERROR: BinomialRng::innerSetN - n must be a positive integer." << endl; - return; - } - - if(!isNSet_) - { - isNSet_ = true; - n_ = n; - } - else - { - if (n_!= n ) - { - n_ = n; - isModified_ = true; - } - } - - if ( isNSet_ && isPSet_ && isModified_) - { { - if ( rng_ ) - { - delete rng_; - } - rng_ = new Binomial((unsigned long)n_,p_); - isModified_ = false; - } - } -} - -/** - Returns parameter n. - */ -double BinomialRng::getN() const -{ - return n_; -} - -/** - Set parameter p ( the probability of the outcome of interest ). - This must be set before the actual generator is instantiated. - */ -void BinomialRng::setP(double p) -{ - if ( p < 0 || p > 1) { - cerr << "ERROR: BinomialRng::setP - p must be in (0,1) range." << endl; - return; - } - if ( !isPSet_) { - p_ = p; - isPSet_ = true; - } else { - if (!isClose< double >(p_,p, DBL_EPSILON)) { - p_ = p; - isModified_ = true; - } - } - - if ( isNSet_ && isPSet_ && isModified_ ){ - if ( rng_ ){ - delete rng_; - } - rng_ = new Binomial((long)(n_),p_); - isModified_ = false; - } -} - -/** - returns parameter p. -*/ -double BinomialRng::getP() const -{ - return p_; -} - - -/** - reports error if one or more of the parameters are not set. -*/ -void BinomialRng::vReinit( const Eref& e, ProcPtr p) -{ - if ( isNSet_ ){ - if ( isPSet_ ){ - if ( !rng_ ){ - rng_ = new Binomial((unsigned long)(n_), p_); - } - } else { - cerr << "ERROR: BinomialRng::reinit - first set value of p." << endl; - } - } else { - cerr << "ERROR: BinomialRng::reinit - first set value of n." << endl; - } -} - - -#endif diff --git a/moose-core/randnum/BinomialRng.h b/moose-core/randnum/BinomialRng.h deleted file mode 100644 index df470a5100c1548262fc5b7f51e6ba9e90f270ce..0000000000000000000000000000000000000000 --- a/moose-core/randnum/BinomialRng.h +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************* - * File: BinomialRng.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 10:48:59 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _BINOMIALRNG_H -#define _BINOMIALRNG_H - -#include "randnum.h" -#include "../basecode/header.h" -#include "RandGenerator.h" -#include "Binomial.h" - -class BinomialRng: public RandGenerator -{ - public: - BinomialRng(); - void setN(double n); - double getN() const; - void setP(double p); - double getP() const; - virtual void vReinit( const Eref& e, ProcPtr p); - - static const Cinfo * initCinfo(); - private: - bool isNSet_; - unsigned long n_; - bool isPSet_; - double p_; - bool isModified_; -}; - -#endif diff --git a/moose-core/randnum/CMakeLists.txt b/moose-core/randnum/CMakeLists.txt index 343f7f7fa0d67a9f3c3384493d712f279b8c42da..cc4de6b76f7791ed222525d41f499689770447dc 100644 --- a/moose-core/randnum/CMakeLists.txt +++ b/moose-core/randnum/CMakeLists.txt @@ -1,8 +1,11 @@ -file(GLOB random_SRC "*.cpp") +cmake_minimum_required(VERSION 2.8) -include_directories(../basecode ) -if(WITH_GSL) - include_directories(${GSL_INCLUDE_DIRS}) -endif(WITH_GSL) +if( ${CMAKE_SOURCE_DIR} EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ) + add_definitions( -std=c++11 -g -Wall ) +endif() -add_library(randnum ${random_SRC}) +add_executable( normal_dist + ${CMAKE_CURRENT_SOURCE_DIR}/test_normal_dist.cpp) + +enable_testing() +add_test( NAME test_normal_dist COMMAND $<TARGET_FILE:normal_dist> ) diff --git a/moose-core/randnum/Definitions.h b/moose-core/randnum/Definitions.h new file mode 100644 index 0000000000000000000000000000000000000000..19ef33fa5a6c78cd4da6fa77a12696de638f7028 --- /dev/null +++ b/moose-core/randnum/Definitions.h @@ -0,0 +1,46 @@ +/*** + * Filename: Definitions.h + * + * Description: Various definitions. + * + * Version: 0.0.1 + * Created: 2018-08-04 + + * Revision: none + * + * Author: Dilawar Singh <dilawars@ncbs.res.in> + * Organization: NCBS Bangalore + * + * License: GNU GPL3 + */ + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#include <random> + +namespace moose { + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis MOOSE's random device. Use it from <random> + */ +/* ----------------------------------------------------------------------------*/ +typedef std::random_device MOOSE_RANDOM_DEVICE; + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Global random number generator engine. Everywhere we use this + * engine. + */ +/* ----------------------------------------------------------------------------*/ +typedef std::mersenne_twister_engine< std::uint_fast32_t, 32, 624, 397, 31 + , 0x9908b0df, 11 + , 0xffffffff, 7 + , 0x9d2c5680, 15 + , 0xefc60000, 18, 1812433253 + > MOOSE_RNG_DEFAULT_ENGINE; + +} + +#endif /* end of include guard: DEFINITIONS_H */ diff --git a/moose-core/randnum/Distributions.h b/moose-core/randnum/Distributions.h new file mode 100644 index 0000000000000000000000000000000000000000..d58fd905938ec5f7457d1d03b2a1584197b445c4 --- /dev/null +++ b/moose-core/randnum/Distributions.h @@ -0,0 +1,34 @@ +/*** + * Filename: Distributions.h + * + * Description: All distributions. + * + * Version: 0.0.1 + * Created: 2018-08-04 + + * Revision: none + * + * Author: Dilawar Singh <dilawars@ncbs.res.in> + * Organization: NCBS Bangalore + * + * License: GNU GPL2 + */ + +#ifndef DISTRIBUTIONS_H +#define DISTRIBUTIONS_H + +#include "NormalDistribution.hpp" +#include <random> + +namespace moose { + + template<typename T=double> + using MOOSE_UNIFORM_DISTRIBUTION = std::uniform_real_distribution<T>; + + template<typename T=double> + using MOOSE_NORMAL_DISTRIBUTION = moose::normal_distribution<T>; + +} + + +#endif /* end of include guard: DISTRIBUTIONS_H */ diff --git a/moose-core/randnum/Exponential.cpp b/moose-core/randnum/Exponential.cpp deleted file mode 100644 index 99f7770db0a0f3158990e8e0a112185cea9187fa..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Exponential.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************* - * File: Exponential.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-01 09:03:51 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _EXPONENTIAL_CPP -#define _EXPONENTIAL_CPP -#include "Exponential.h" -#include "randnum.h" -#include "utility/numutil.h" -#include <iostream> -#include <cmath> - -using namespace std; - -Exponential::Exponential(double mean):mean_(mean),generator_(&(Exponential::randomMinimization)) -{ -} - -Exponential::Exponential(ExponentialGenerator method, double mean):mean_(mean) -{ - switch(method) - { - case LOGARITHMIC: - generator_ = &(Exponential::logarithmic); - break; - default: - generator_ = &(Exponential::randomMinimization); - break; - } -} - -double Exponential::getMean() const -{ - return mean_; -} - -double Exponential::getVariance() const -{ - return mean_*mean_; -} - -double Exponential::getNextSample() const -{ - return generator_(mean_); -} - - -double Exponential::logarithmic(double mean) -{ - double uniform = mtrand(); - if ( uniform <= 0 ) - { - uniform = 1.0e-6; - } - - return - mean*log(uniform); -} - -extern unsigned long genrand_int32(void); - -/** - successive entries in the series - {Qk} = {(ln2/1! + (ln2)^2/2! + (ln2)^3/3! + ... + (ln2)^k/k!)} - used in the random minimization algorithm. - */ -static const double q[] = -{ - 1.0, // dummy for q[0] - 0.69314718055994528622676, - 0.93337368751904603580982, - 0.98887779618386761892879, - 0.99849592529149611142003, - 0.99982928110613900063441, - 0.99998331641007276449074, - 0.99999856914387685868917, - 0.99999989069255590390384, - 0.99999999247341597730099, - 0.99999999952832763217003, - 0.99999999997288147035590 // > 0.99999999953433871269226 = 1 - 2^(-31) -}; - -/** - See Knuth, Vol II Sec 3.4.1 : Algorithm S - */ - -double Exponential::randomMinimization(double mean) -{ - double result; - - unsigned long uniform = genrand_int32(); // 1) generate t+1 (=32) bit uniform random binary fraction .b0..bt - int j = 0; - - if ( uniform == 0 ) - { - uniform = 1; - } - - while (0x80000000 & uniform ) // 1) detect the first 0 bit - { - uniform = uniform << 1; // 1a) shift off leading j+1 bits, setting u = .b(j+1) .. b(t) - ++j; - } - uniform = uniform << 1; // 1a)shift off leading j+1 bits, setting u = .b(j+1) .. b(t) - double uniform_frac = uniform / 4294967296.0; - - if ( uniform_frac < LN2 ) // 2) u < ln2? - { - result = mean*(j*LN2 + uniform_frac); // x <- mean * ( j * ln2 + u ) - } - else - { - // 3) minimize - unsigned int k = 2; - unsigned long v = ~0UL; - unsigned long u; - - while ( ( uniform_frac >= q[k] )) - { - k++; - } - for ( unsigned int i = 0; i < k; ++i ) - { - u = genrand_int32(); - if ( u < v ) - { - v = u; - } - } - - result = mean*( j + v/4294967296.0 )*LN2; - } - - return result; -} -#if 0 // test main -#include <vector> -int main(void) -{ - double mean = .25; - double sum = 0.0; - double sd = 0.0; - vector <unsigned> classes; - Exponential ex(mean); - int MAX_SAMPLE = 100000; - int MAX_CLASSES = 1000; - - - for ( int i = 0; i < MAX_CLASSES; ++i ) - { - classes.push_back(0); - } - - for ( int i = 0; i < MAX_SAMPLE; ++i ) - { - double p = ex.getNextSample();//aliasMethod(); - int index = (int)(p*MAX_CLASSES); -// cout << index << " ] " << p << endl; - - if ( index < MAX_CLASSES){ - classes[index]++; - } - else - { - classes[MAX_CLASSES-1]++; - } - - - sum += p; - sd += (p - mean)*(p - mean); - } - mean = sum/MAX_SAMPLE; - sd = sqrt(sd/MAX_SAMPLE); - cout << "mean = " << mean << " sd = " << sd << endl; - for ( int i = 0; i < MAX_CLASSES; ++i ) - { - cout << classes[i] << endl; - } - - return 0; -} -#endif // test main - - -#endif diff --git a/moose-core/randnum/Exponential.h b/moose-core/randnum/Exponential.h deleted file mode 100644 index 7c92e0884ae790c77be386fe05fc1de9715b2dc7..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Exponential.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************* - * File: Exponential.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-01 08:59:47 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _EXPONENTIAL_H -#define _EXPONENTIAL_H -#include "Probability.h" -enum ExponentialGenerator -{ - LOGARITHMIC, - RANDOM_MINIMIZATION -}; - - -class Exponential: public Probability -{ - public: - Exponential(double mean); - Exponential( ExponentialGenerator generator, double mean); - - double getMean() const; - double getVariance() const; - double getNextSample() const; - private: - double mean_; - double (*generator_)(double); - static double logarithmic(double mean); - static double randomMinimization(double mean); - - -}; - - - -#endif diff --git a/moose-core/randnum/ExponentialRng.cpp b/moose-core/randnum/ExponentialRng.cpp deleted file mode 100644 index 9b9bbada08537ddd6913bb2b93ae5f6a814a1023..0000000000000000000000000000000000000000 --- a/moose-core/randnum/ExponentialRng.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************* - * File: ExponentialRng.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 11:33:45 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _EXPONENTIALRNG_CPP -#define _EXPONENTIALRNG_CPP - -#include "RandGenerator.h" -#include "ExponentialRng.h" - -const Cinfo* ExponentialRng::initCinfo() -{ - static ValueFinfo< ExponentialRng, double > mean( - "mean", - "Mean of the exponential distribution.", - &ExponentialRng::setMean, - &ExponentialRng::getMean); - - static ValueFinfo< ExponentialRng, int > method( - "method", - "The algorithm to use for computing the sample. Two methods are" - " supported: 0 - logarithmic and 1 - random minimization." - " The logarithmic method is slower (it computes a" - " logarithm). Default is random minimization. See Knuth, Vol II Sec" - " 3.4.1 : Algorithm S.", - &ExponentialRng::setMethod, - &ExponentialRng::getMethod); - - static Finfo* exponentialRngFinfos[] = { - &mean, - &method, - }; - - static string doc[] = { - "Name", "ExponentialRng", - "Author", "Subhasis Ray", - "Description", "Exponentially distributed random number generator.\n" - "Exponential distribution with mean k is defined by the probability" - " density function p(x; k) = k * exp(-k * x) if x >= 0, else 0." - " By default this class uses the random minimization method" - " described in Knuth's TAOCP Vol II Sec 3.4.1 (Algorithm S).", - }; - static Dinfo< ExponentialRng > dinfo; - static Cinfo exponentialRngCinfo( - "ExponentialRng", - RandGenerator::initCinfo(), - exponentialRngFinfos, - sizeof(exponentialRngFinfos)/sizeof(Finfo*), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - return &exponentialRngCinfo; -} - - -static const Cinfo* exponentialRngCinfo = ExponentialRng::initCinfo(); - -ExponentialRng::ExponentialRng() -{ - mean_ = 0; - isMeanSet_ = false; - method_ = RANDOM_MINIMIZATION; -} -/** - Replaces the same method in base class. Returns the mean as - stored in this object independent of the actual generator object. - */ -double ExponentialRng::getMean() const -{ - return mean_; -} -/** - Sets the mean. Since exponential distribution is defined in terms - of this parameter, it is stored locally independent of the - instantiation of the internal generator object. -*/ -void ExponentialRng::setMean(double mean) -{ - if ( !rng_ ){ - rng_ = new Exponential(mean); - isMeanSet_ = true; - } -} - -/** - Reports error in case the parameter mean has not been set. - */ -void ExponentialRng::vReinit(const Eref& e, ProcPtr p) -{ - Exponential * erng = static_cast<Exponential *>(rng_); - if (!erng){ - cerr << "ERROR: ExponentialRng::vReinit - mean must be set before using the Exponential distribution generator." << endl; - } -} - -/** - Returns the algorithm used for sample generation. - 0 for logarithmic method. - 1 for random minimization method. - */ -int ExponentialRng::getMethod() const -{ - return method_; -} - -/** - Sets the algorithm used for sample generation. - 0 for logarithmic method. - 1 for random minimization method. - Default is random minimization. - */ -void ExponentialRng::setMethod(int method) -{ - Exponential * erng = static_cast< Exponential * >(rng_); - if (!erng){ - switch ( method ){ - case 0: - method_ = LOGARITHMIC; - break; - default: - method_ = RANDOM_MINIMIZATION; - break; - } - } else { - cerr << "Warning: Will not change method after generator object has been" - << " created. Method in use:" - << method << " (" - << (method == 0? "logarithmic": "random minimization") - << ")" << endl; - } -} - -#endif diff --git a/moose-core/randnum/ExponentialRng.h b/moose-core/randnum/ExponentialRng.h deleted file mode 100644 index 08a8c2452bfaa0e6145c3ce962aef39d310b1697..0000000000000000000000000000000000000000 --- a/moose-core/randnum/ExponentialRng.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************* - * File: ExponentialRng.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 11:27:50 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _EXPONENTIALRNG_H -#define _EXPONENTIALRNG_H -#include "randnum.h" -#include "../basecode/header.h" -#include "RandGenerator.h" -#include "Exponential.h" - -/** - This is MOOSE wrapper for Exponentially distributed random number generator class, Exponential. - The default - */ -class ExponentialRng: public RandGenerator -{ - public: - ExponentialRng(); - double getMean() const; - void setMean(double mean); - int getMethod() const; - void setMethod(int method); - virtual void vReinit( const Eref& e, ProcPtr p); - - static const Cinfo* initCinfo(); - - private: - double mean_; - bool isMeanSet_; - int method_; - -}; - - -#endif diff --git a/moose-core/randnum/Gamma.cpp b/moose-core/randnum/Gamma.cpp deleted file mode 100644 index e2eb58ea2be8995081950bf94be67bd29835a7ca..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Gamma.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/******************************************************************* - * File: Gamma.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-05 18:33:01 - ********************************************************************/ -/********************************************************************** - ** This program is part of 'MOOSE', the - ** Messaging Object Oriented Simulation Environment, - ** also known as GENESIS 3 base code. - ** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS - ** It is made available under the terms of the - ** GNU General Public License version 2 - ** See the file COPYING.LIB for the full notice. - **********************************************************************/ - -#ifndef _GAMMA_CPP -#define _GAMMA_CPP -#include <cmath> -#include "utility/numutil.h" -#include "Gamma.h" -#include "Exponential.h" -#include "randnum.h" -Gamma::Gamma(double alpha, double theta):alpha_(alpha), theta_(theta) -{ - if (( alpha < 0 ) || (theta < 0 )) - { - cerr << "ERROR: setting parameter of Gamma distribution to negative. Setting both to 1." << endl; - alpha_ = 1; - theta_ = 1; - } -} -double Gamma::getAlpha() -{ - return alpha_; -} - -double Gamma::getTheta() -{ - return theta_; -} - -double Gamma::getMean() const -{ - return alpha_*theta_; -} - -double Gamma::getVariance() const -{ - return alpha_*theta_*theta_; -} - -double Gamma::getNextSample() const -{ - double result; - - if ( alpha_ <= 1 ) - { - result = gammaSmall(); - } - else - { - result = gammaLarge(); - } - if ( !isClose< double >(theta_, 1.0, DBL_EPSILON)) - { - result *= theta_; - } - - return result; -} - -// See Algorithm A in TAOCP by Knuth, Vol 2 ,Section 3.4.1 -double Gamma::gammaLarge() const// alpha > 1 -{ - double result = 0.0; - // a1. generate candidate - double yValue; - double uniformU; - double uniformV; - double check; - double tmp; - - while (true) - { - uniformU = mtrand(); - yValue = tan(M_PI*uniformU); - tmp = sqrt(2*alpha_ - 1)*yValue; - - result = tmp + alpha_ - 1; - if (result > 0) - { - uniformV = mtrand(); - check = ( 1 + yValue*yValue )*exp((alpha_ - 1.0)*log(result/(alpha_ - 1.0)) - tmp); - if (uniformV < check ) - { - return result; - } - } - } - return result; // silence the compiler -} - - -// See: TAOCP by Knuth, Vol 2, 3.4.1 Exercise 16 -double Gamma::gammaSmall() const // 0 < alpha < 1 -{ - static Exponential expGen(1.0); - - // G1. initialize - static double p = NATURAL_E/(alpha_+NATURAL_E); - static double pByE = 1.0/(alpha_+NATURAL_E); - double uniformU; - double expSample; - double xValue = 0.0; - double qValue; - - while ( true ) - { - // G2. generate G deviate - uniformU = mtrand(); - expSample = expGen.getNextSample(); - while (expSample == 0 ) - { - expSample = expGen.getNextSample(); - } - - if ( uniformU < p ) - { - xValue = exp(-expSample/alpha_); - if ( uniformU < pByE ) - { - return xValue; - } - qValue = p*exp(-xValue); - } - else - { - xValue = 1 + expSample; - qValue = p + (1.0-p)*pow(xValue, alpha_ - 1.0); - } - - // G3. reject? - if ( uniformU < qValue ) - { - return xValue; - } - } - return xValue; // silence the compiler -} - - -#endif diff --git a/moose-core/randnum/Gamma.h b/moose-core/randnum/Gamma.h deleted file mode 100644 index 2812c76277fb62dade6e5c3fe54d031e61055376..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Gamma.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************* - * File: Gamma.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-05 19:22:32 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _GAMMA_H -#define _GAMMA_H -#include "Probability.h" -#include <iostream> -using namespace std; - -class Gamma: public Probability -{ - public: - Gamma(double alpha, double theta); - double getAlpha(); - double getTheta(); - double getMean() const; - double getVariance() const; - double getNextSample() const; - private: - double alpha_; - double theta_; - double gammaSmall() const; - double gammaLarge() const; - -}; - - -#endif diff --git a/moose-core/randnum/GammaRng.cpp b/moose-core/randnum/GammaRng.cpp deleted file mode 100644 index eac78fbaefe2e94e17921902a4dcec532320d1dd..0000000000000000000000000000000000000000 --- a/moose-core/randnum/GammaRng.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************* - * File: GammaRng.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 11:56:00 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _GAMMARNG_CPP -#define _GAMMARNG_CPP -#include "GammaRng.h" -#include "utility/numutil.h" -#include <cmath> - -const Cinfo* GammaRng::initCinfo() -{ - static ValueFinfo< GammaRng, double > alpha( - "alpha", - "Parameter alpha of the gamma distribution.", - &GammaRng::setAlpha, - &GammaRng::getAlpha); - static ValueFinfo< GammaRng, double > theta( - "theta", - "Parameter theta of the Gamma distribution.", - &GammaRng::setTheta, - &GammaRng::getTheta); - static Finfo* gammaRngFinfos[] = { - &alpha, - &theta, - }; - - static string doc[] = { - "Name", "GammaRng", - "Author", "Subhasis Ray", - "Description", "Gamma distributed random number generator.", - }; - - Dinfo < GammaRng > dinfo; - static Cinfo gammaRngCinfo( - "GammaRng", - RandGenerator::initCinfo(), - gammaRngFinfos, - sizeof(gammaRngFinfos)/sizeof(Finfo*), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - return &gammaRngCinfo; -} - - -static const Cinfo* gammaRngCinfo = GammaRng::initCinfo(); - -GammaRng::GammaRng() -{ - isAlphaSet_ = false; - isThetaSet_ = false; - alpha_ = 1; - theta_ = 1; -} -/** - returns the shape parameter. -*/ -double GammaRng::getAlpha() const -{ - return alpha_; -} -/** - Sets parameter alpha. Also known as the shape parameter. -*/ -void GammaRng::setAlpha(double alpha) -{ - - if (fabs(alpha) < DBL_MIN) - { - cerr << "ERROR: Shape parameter alpha must be non-zero." << endl; - return; - } - Gamma * grng = static_cast< Gamma * >(rng_); - if ( grng ) { - alpha_ = grng->getAlpha(); - } else { - alpha_ = alpha; - isAlphaSet_ = true; - if ( isThetaSet_ ){ - rng_ = new Gamma(alpha_, theta_); - } - } -} -/** - returns the scale parameter. -*/ -double GammaRng::getTheta()const -{ - return theta_; -} - -/** - Sets parameter theta. Also known as the scale parameter. -*/ -void GammaRng::setTheta(double theta) -{ - - if (fabs(theta) < DBL_MIN) - { - cerr << "ERROR: Scale parameter theta must be non-zero." << endl; - return; - } - Gamma* grng = static_cast<Gamma*>(rng_); - if ( grng ){ - theta_ = grng->getTheta(); - } else { - theta_ = theta; - isThetaSet_ = true; - if (isAlphaSet_ ){ - rng_ = new Gamma(alpha_, theta_); - } - } -} -/** - reports error if parameters have not been set properly. -*/ -void GammaRng::vReinit(const Eref& e, ProcPtr p) -{ - if (! rng_ ) - { - cerr << "ERROR: GammaRng::vReinit - parameters alpha and theta must be set before using the Gamma distribution generator." << endl; - } -} - -#endif diff --git a/moose-core/randnum/GammaRng.h b/moose-core/randnum/GammaRng.h deleted file mode 100644 index 381da44e74b09c581326721e8365e07b8ea760e9..0000000000000000000000000000000000000000 --- a/moose-core/randnum/GammaRng.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************* - * File: GammaRng.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 11:53:29 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _GAMMARNG_H -#define _GAMMARNG_H -#include "randnum.h" -#include "basecode/header.h" -#include "RandGenerator.h" -#include "Gamma.h" - -/** - This is MOOSE wrapper for Gammaly distributed random number generator class, Gamma. - The default - */ -class GammaRng: public RandGenerator -{ - public: - GammaRng(); - virtual ~GammaRng() { ; } - double getAlpha() const; - double getTheta() const; - void setAlpha(double alpha); - void setTheta(double theta); - - virtual void vReinit( const Eref& e, ProcPtr p); - - static const Cinfo * initCinfo(); - - private: - double alpha_; - double theta_; - - bool isAlphaSet_; - bool isThetaSet_; -}; - - -#endif diff --git a/moose-core/randnum/Normal.cpp b/moose-core/randnum/Normal.cpp deleted file mode 100644 index 608ce92804319037370324513fd2a8b070e534aa..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Normal.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/******************************************************************* - * File: Normal.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-10-31 13:48:53 - ********************************************************************/ -/********************************************************************** - ** This program is part of 'MOOSE', the - ** Messaging Object Oriented Simulation Environment, - ** also known as GENESIS 3 base code. - ** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS - ** It is made available under the terms of the - ** GNU General Public License version 2 - ** See the file COPYING.LIB for the full notice. - **********************************************************************/ - -#ifndef _NORMAL_CPP -#define _NORMAL_CPP -#include "Normal.h" -#include "randnum.h" -#include "../utility/numutil.h" -#include <cmath> -#include <iostream> -using namespace std; - -extern unsigned long genrand_int32(void); -Normal::Normal(double mean, double variance, NormalGenerator method):mean_(mean), variance_(variance), method_(method) -{ - if (variance <= 0.0 ) - { - cout << "Warning: cannot set variance <= 0. Setting to 1.0." << endl; - variance_ = 1.0; - } - - isStandard_ = isClose< double >(0.0, mean, DBL_EPSILON) && isClose < double > (1.0, variance, DBL_EPSILON); - switch(method) - { - case ALIAS: - generator_ = &(Normal::aliasMethod); - break; - case BOX_MUELLER: - generator_ = &(Normal::BoxMueller); - break; -#ifdef USE_GSL - case ZIGGURAT: - generator_ = &(Normal::gslZiggurat); - break; -#endif - default: - cerr << "ERROR: Normal() - generator method# " << method << ". Don't know how to do this. Using alias method."<<endl; - generator_ = &(Normal::aliasMethod); - } -} - -double dummy() -{ - return 0.0; -} - -double Normal::getNextSample() const -{ - double sd = sqrt(variance_); - double sample = generator_(); - if (!isStandard_) - { - sample = mean_ + sd*sample; - } - return sample; -} - -double Normal::getMean() const -{ - return mean_; -} - -void Normal::setMean( double mean) -{ - mean_ = mean; - isStandard_ = isClose< double >(0.0, mean_, DBL_EPSILON) && isClose< double >(1.0, variance_, DBL_EPSILON); -} - -double Normal::getVariance() const -{ - return variance_; -} - -void Normal::setVariance( double variance ) -{ - if (variance <= 0.0) - { - cout << "Warning: cannot set variance < 0." << endl; - return; - } - variance_ = variance; - isStandard_ = isClose< double > (0.0, mean_, DBL_EPSILON) && isClose< double >(1.0, variance_, DBL_EPSILON); -} - -NormalGenerator Normal::getMethod(void) -{ - return method_; -} - -void Normal::setMethod(NormalGenerator method) -{ - method_ = method; - switch(method) - { - case ALIAS: - generator_ = &(Normal::aliasMethod); - break; - case BOX_MUELLER: - generator_ = &(Normal::BoxMueller); - break; -#ifdef USE_GSL - case ZIGGURAT: - generator_ = &(Normal::gslZiggurat); - break; -#endif - default: - cerr << "ERROR: Normal() - generator method# " << method << ". Don't know how to do this. Using alias method."<<endl; - generator_ = &(Normal::aliasMethod); - method_ = ALIAS; - } -} - -#ifdef USE_GSL -#include <gsl/gsl_rng.h> -#include <gsl/gsl_randist.h> - -double Normal::gslZiggurat() -{ - static const gsl_rng_type * T; - static gsl_rng * r; - static bool inited = false; - if (!inited) - { - /* create a generator chosen by the - environment variable GSL_RNG_TYPE */ - - gsl_rng_env_setup(); - - T = gsl_rng_default; - r = gsl_rng_alloc (T); - inited = true; - } - return gsl_ran_gaussian_ziggurat(r, 1.0); -} - -#endif // !USE_GSL -/** - Very simple but costly implementation -*/ -double Normal::BoxMueller() -{ - double result; - double a, b, r; - do - { - a = 2.0 * mtrand() - 1.0; - b = 2.0 * mtrand() - 1.0; - r = a * a + b * b; - } while ( r >= 1.0 ); - r = sqrt( - 2.0 * log(r) / r ); - result = r * a; - - return result; -} -/** - Refer to: - Eine Alias-Methode zur Stichprohenentnahme aus Normalverteilungen. - JH Ahrens and U Dieter, 19 89, Computing - - We are assuming size of long to be 32 bit -*/ - -const unsigned long y[] = -{ - 200, 199, 199, 198, 197, 196, 195, 193, 192, 190, 188, 186, 184, 181, 179, 176, 173, 170, 167, 164, 161, 157, 154, 151, 147, 143, 140, 136, 132, 128, 125, 121, 117, 113, 110, 106, 102, 98, 95, 91, 88, 84, 81, 77, 74, 71, 68, 64, 61, 59, 56, 53, 50, 48, 45, 43, 40, 38, 36, 34, 32, 30, 28, 27, 25, 23, 22, 20, 19, 18, 17, 15, 14, 13, 12, 11, 11, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -const long a[] = -{ - 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 27, 26, 25, 24, 23, 22, 21, -1, 19, 19, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 -}; - -const unsigned long q[] = -{ - 28, 32, 33, 36, 40, 43, 45, 47, 51, 53, 57, 59, 27, 37, 43, 54, 28, 45, 60, 63, 49, 61, 52, 34, 63, 46, 34, 18, 47, 40, 36, 29, 61, 57, 53, 51, 47, 43, 40, 37, 33, 31, 27, 25, 21, 19, 17, 14, 11, 9 , 8, 5, 54, 51, 49, 46, 44, 41, 39, 37, 35, 33, 31, 29, 28, 26, 24, 23, 21, 20, 19, 18, 16, 15, 14, 13, 12, 12, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; -const double c = 0.004996971959878404; - -const double d = 1.861970434352886050; -/*********************************************************************************************************************************/ -/* TODO: This implementation has a bug. The sample mean deviates a lot - * from the generator mean for very small numbers, like 1e-7 - * Need to make sure that this is not due to 32/64 bit incompatibility. - */ -/*********************************************************************************************************************************/ -double Normal::aliasMethod() -{ - double result; - - unsigned long uniform; - unsigned long uniform_prime; - unsigned long x_num; - unsigned long t_num; - unsigned long v_num; - - unsigned long i_num, k_num, sgn; - - while (true) - { - - // 1) u = .B1..B7 (base 256) - we take the little endian approach - uniform = genrand_int32(); // .B1B2B3B4 - limited by precision - - // 1a) s = B1[0] - sgn = uniform & 0x80000000UL; - // 1b) B1[0] = 0 - uniform = uniform & 0x7fffffffUL; - - // 2) i = B1[1..7] - i_num = uniform >> 24; - // 3) k = (B2 ^ B4) and retain least significant 6 bits of k - k_num = ((uniform >> 16) ^ uniform ) & 0x0000003fUL; - - // 4) k <q[i]? goto 7 - if ( k_num >= q[i_num] ) - { - // 5) i = a[i] - i_num = a[i_num]; - - // 5a)i = ~0? goto 11 - if (i_num != ~(0UL)) - { - - // 6) B1 = i - uniform = (uniform & 0x00ffffffUL) | (i_num << (WORD_LENGTH-8)); - - // 6a) x = 8*u - x_num = uniform << 3; - - // 6b) goto 8 - s = 0? return x: return -x - // result = x_num/4294967296.0; // convert to double -// result = (sgn == 0) ? result : -result; - //return result; - break; - } - } - else - { - - - // 7) x = 8*u - x_num = uniform << 3; - - // 7a) if (k <= y[i-1] - y[i]) goto 9 - if (k_num > y[i_num-1] - y[i_num]) - { - // 8) s = 0? return x: return -x -// result = x_num/4294967296.0; // convert to double -// result = (sgn == 0) ? result : -result; - //return result; - break; - - } - - // 9) u' = .B1'..B7' .. using B1-B4 for precision limitation - uniform_prime = genrand_int32(); - // 9a) t = x*x/2 - t_num = x_num*(x_num/2); - - // 9b) v = c*(y[i] + u'*(y[i-1] - y[i] + 1)) - v_num = (unsigned long)(c*(y[i_num] + uniform_prime*(y[i_num - 1] - y[i_num] + 1))); - - // 10) v > exp(-t)? goto 1: goto 8 - - - if ( testAcceptance(t_num, v_num )) - { - result = x_num/4294967296.0; // convert to double - result = (sgn == 0) ? result : -result; - //return result; - break; - - }else - { - continue; - } - } - - // 11) u = .B1..B7 - uniform = genrand_int32(); - - // 11a) u < 1/9? goto 1 - if ( uniform/4294967296.0 < 1.0/9.0) - { - continue; - } - - // 12) x = 3.75 + 0.25/u - unsigned long divider = ((uniform << 24) + - ((uniform << 16) & 0x00ff0000UL) + - ((uniform << 8) & 0x0000ff00UL) + - (uniform & 0x000000ffUL)); - - x_num = (unsigned long)( 3.75 + (1.0*0x40000000UL)/divider); - // 12a) t = x*x/2-8, v = d*u*u*u' - t_num = x_num*x_num/2 - 0x8UL; - v_num = (unsigned long)(d*uniform*uniform*uniform_prime); - - // 12b) goto 10 - // 10) v > exp(-t)? goto 1: goto 8 - if ( testAcceptance(t_num, v_num) ) - { - // 8) -// result = x_num/4294967296.0; // convert to double -// result = (sgn == 0) ? result : -result; -// return result; - break; - - - }else // goto 1 - { - continue; - } - } - // 8) - result = (sgn == 0) ? x_num/4294967296.0 : -(x_num/4294967296.0); - - return result; - -} -/** - Method to check if v > exp(-t) without doing the exponentiation - TODO: try to do everything in integer arithmetic -*/ -bool Normal::testAcceptance(unsigned long t_num, unsigned long v_num) -{ - bool accept = false; - bool cont = true; - - double t = t_num/4294967296.0; - double v = v_num/4294967296.0; -// return (v > exp(-t)); - - while(cont) - { // a) - if ( t >= LN2 ) - { - // b) - t = t - LN2; - v += v; - - if ( v > 1 ) - { - return false; - } - else - { - continue; - } - } - // c) - v = v + t - 1; - if ( v <= 0 ) - { - return true; - } - // d) - double r = t * t; - v = v + v - r; - if ( v > 0) - { - return false; - } - double c = 3.0; - // e) - while(true) - { - r *= t; - v = v * c + r; - if ( v <= 0) - { - return true; - } - c += 1.0; - // f) - r *= t; - v = v * c - r; - if ( v > 0 ) - { - return false; - } - c += 1.0; - } - } - return accept; -} - -/** - See Knuth, TAOCP Vol 2 Sec 3.4.1 - Algorithm M: The Rectangle-wedge-tail method discovered by G Marsaglia - TODO: implement it by filling the gaps -*/ -#if 0 -double algorithmM() // not implemented -{ - cout << "algorithmM() - not yet implemented." << endl; - return 0.0; - - double result; - double u; - int psi; - // TODO: construct these auxiliary tables. - static int P[32]; - static int Q[32]; - static int Y[32]; - static int Z[32]; - static int S[32]; - static int D[32]; - static int E[32]; - // M1 [ Get U ] - // U = (.b0b1b2....bt)2 - u = mtrand(); - // M2 [Rectangle?] - // psi = b0 - // j = (b1b2b3b4b5)2 - // f = (.b6b7..bt)2 - // if ( f >= Pj ) { X = Yj + f*Zj; goto M9 } - // else if ( j <= 15, i.e. b1 == 0 ) { X = Sj + f*Qj; goto M9 } - - // M3 [ Wedge or tail? ] - // Now 15 <= j <= 31 and each particular value j occurs with probability pj - // if ( j == 31 ) goto M7 - - // M4 [ Get U <= V ] - // Generate two new uniform deviates, U and V; if U > V, exchange U <-> V - // Set X =S(j-15) + U/5 - - // M5 [ Easy case? ] - // if ( V <= Dj ) goto M9 - - // M6 [ Another try? ] - // if ( V > U + Ej * (exp[( S(j-14)^2 - X^2 )/2] - 1 ) ) goto M4 - // else goto M9 - - // M7 [ Get supertail deviate ] - // Generate two new independent uniform deviates U and V - // set X = sqrt(9-2*lnV) - - // M8 [ Reject? ] - // if ( U*X >= 3 ) goto M7 - - // M9 [ Attach sign ] - // if ( psi == 1 ) X = -X - - return result; -} -#endif -/** - TODO: Not yet implemented. -*/ -double algorithmF() -{ - cout << "algorithmF() - not implemented." << endl; - - double result = 0; - return result; -} - - -#ifdef DO_UNIT_TESTS -#include <cassert> -#include <vector> - -void checkMeanVariance(Normal& normalGen, unsigned seqLen) -{ - vector < double > seq; - double mean = 0.0; - for ( unsigned ii = 0; ii < seqLen; ++ii) - { - double sample = normalGen.getNextSample(); - seq.push_back(sample); - mean += sample; - } - mean /= seqLen; - cout << "Testing Normal: " << normalGen.getMethod() << " method for " << seqLen << " samples :: mean set - " << normalGen.getMean() << ", sample mean - " << mean << ". "; - double variance = 0.0; - for ( unsigned ii = 0; ii < seqLen; ++ ii) - { - variance += (mean - seq[ii]) * (mean - seq[ii]); - } - variance /= seqLen; - cout << "variance set - " << normalGen.getVariance() << ", sample variance - " << variance << endl; -} - -void testNormal() -{ - // const unsigned SEQ_LEN = 1000; - - Normal* normalGen = new Normal(); - // make sure default constructor creates standard normal - assert(isClose< double >(normalGen->getMean(), 0.0, DBL_EPSILON)); - assert(isClose< double > (normalGen->getVariance(), 1.0, DBL_EPSILON)); - // check if setting method is effective - normalGen->setMethod(ALIAS); - assert(normalGen->getMethod() == ALIAS); - checkMeanVariance(*normalGen, 1000); // check the sample mean and variance for "alias method" - delete normalGen; - normalGen = new Normal(100.0, 33.0, BOX_MUELLER); - assert(normalGen->getMethod() == BOX_MUELLER); - assert(isClose< double >(normalGen->getMean(), 100.0, DBL_EPSILON)); - assert(isClose(normalGen->getVariance(), 33.0, DBL_EPSILON)); - checkMeanVariance(*normalGen, 1000); // check the sample mean and variance for "Box-Mueller method" - delete normalGen; - - // non standard normal distr. - normalGen = new Normal(); - normalGen->setMean(-100.0); - normalGen->setVariance(3.0); - checkMeanVariance(*normalGen, 1000); -} -#if 0 // keep it out of compilation -void testByte2Double() -{ - double res; - - unsigned char bytes[] = - { - 0, 0, 0, 0, 0 - }; - bytes[4] = 0x5; - res = byte2double(bytes, 5); - printf("0.0000000005 H = %.20g\n", res); - bytes[3] = 0x4; - res = byte2double(bytes, 4); - printf("0.00000004 H = %.20g\n", res); - bytes[2] = 0x3; - res = byte2double(bytes, 3); - printf("0.000003 H = %.20g\n", res); - bytes[1] = 0x2; - res = byte2double(bytes, 2); - printf("0.0002 H = %.20g\n", res); - assert(isClose< double >(res, 0.000030517578125)); - bytes[0] = 0x1; - res = byte2double(bytes, 1); - printf("0.01 H = %.20g\n", res); - assert(res == 0.00390625); - res = byte2double(bytes, 5); - printf("0.0102030405 in hex = %.20g\n", res); - assert(isClose< double >(res, 0.0039369473279293742962, 1e-9));// the right comparison is from the same program. Should check for various architectures. -} -#endif // #if 0 -#endif // !DO_UNIT_TESTS - -#if defined(DO_UNIT_TESTS) && defined(TEST_MAIN) -// Test main - -int main(void) -{ - double mean = 0.0; - double sd = 0.0; - double sum = 0.0; - int freq [200]; - Normal n(BOX_MUELLER); - - for ( int i = 0; i < 200; ++i ) - { - freq[i] = 0; - } - - for ( int i = 0; i < 10000; ++i ) - { - double p = n.getNextSample();//aliasMethod(); - int index = (int)(p*100)+99; - cout << index << " ] " << p << endl; - if ( index < 0 ) - index = 0; - else if ( index > 199 ) - index = 199; - - freq[index]++; - - sum += p; - sd = p*p; - } - mean = sum/1000; - sd = sd/1000; - cout << mean << " " << sd << endl; - for ( int i = 0; i < 200; ++i ) - { - cout << freq[i] << endl; - } - - testNormal(); - - return 0; -} -#endif // ! define(DO_UNIT_TESTS) && defined(TEST_MAIN) - - -#endif diff --git a/moose-core/randnum/Normal.h b/moose-core/randnum/Normal.h deleted file mode 100644 index c74cf9bb3a66405ed6f8fd7e71f1d52da288d44b..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Normal.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************* - * File: Normal.h - * Description: Generates random numbers with normal - * distribution. - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-10-30 11:22:51 - ********************************************************************/ -/********************************************************************** - ** This program is part of 'MOOSE', the - ** Messaging Object Oriented Simulation Environment, - ** also known as GENESIS 3 base code. - ** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS - ** It is made available under the terms of the - ** GNU General Public License version 2 - ** See the file COPYING.LIB for the full notice. - **********************************************************************/ - -#ifndef _NORMAL_H -#define _NORMAL_H -#include "Probability.h" -enum NormalGenerator -{ - ALIAS, - BOX_MUELLER, - ZIGGURAT -}; - -class Normal : public Probability -{ - - public: - Normal(double mean=0.0, double variance=1.0, NormalGenerator algorithm=ALIAS); - double getMean() const; - void setMean(double value); - double getVariance() const; - void setVariance( double value ); - NormalGenerator getMethod(void); - void setMethod(NormalGenerator method); - double getNextSample() const; - private: - double mean_; - double variance_; - double (*generator_)(); - bool isStandard_; - NormalGenerator method_; - static double BoxMueller(); - static double aliasMethod(); - static double gslZiggurat(); - static bool testAcceptance(unsigned long t, unsigned long v); -}; - - -#endif diff --git a/moose-core/randnum/NormalDistribution.hpp b/moose-core/randnum/NormalDistribution.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c79fdf5407bc9446deb3dbca39dec57b7cdd5c17 --- /dev/null +++ b/moose-core/randnum/NormalDistribution.hpp @@ -0,0 +1,197 @@ +/*** + * Generates normally distributed numbers. Based on GSL implementation. + * + * Created: 2018-08-04 + * Author: Dilawar Singh <dilawars@ncbs.res.in> + * Organization: NCBS Bangalore + * License: GNU GPL3 + */ + +#ifndef NORMALDISTRIBUTION_H +#define NORMALDISTRIBUTION_H + +#include "Definitions.h" + +/* position of right-most step */ +#define PARAM_R 3.44428647676 + +namespace moose { +namespace details { + +/* tabulated values for the heigt of the Ziggurat levels */ +static const double ytab[128] = +{ + 1, 0.963598623011, 0.936280813353, 0.913041104253, + 0.892278506696, 0.873239356919, 0.855496407634, 0.838778928349, + 0.822902083699, 0.807732738234, 0.793171045519, 0.779139726505, + 0.765577436082, 0.752434456248, 0.739669787677, 0.727249120285, + 0.715143377413, 0.703327646455, 0.691780377035, 0.68048276891, + 0.669418297233, 0.65857233912, 0.647931876189, 0.637485254896, + 0.62722199145, 0.617132611532, 0.607208517467, 0.597441877296, + 0.587825531465, 0.578352913803, 0.569017984198, 0.559815170911, + 0.550739320877, 0.541785656682, 0.532949739145, 0.524227434628, + 0.515614886373, 0.507108489253, 0.498704867478, 0.490400854812, + 0.482193476986, 0.47407993601, 0.466057596125, 0.458123971214, + 0.450276713467, 0.442513603171, 0.434832539473, 0.427231532022, + 0.419708693379, 0.41226223212, 0.404890446548, 0.397591718955, + 0.390364510382, 0.383207355816, 0.376118859788, 0.369097692334, + 0.362142585282, 0.355252328834, 0.348425768415, 0.341661801776, + 0.334959376311, 0.328317486588, 0.321735172063, 0.31521151497, + 0.308745638367, 0.302336704338, 0.29598391232, 0.289686497571, + 0.283443729739, 0.27725491156, 0.271119377649, 0.265036493387, + 0.259005653912, 0.253026283183, 0.247097833139, 0.241219782932, + 0.235391638239, 0.229612930649, 0.223883217122, 0.218202079518, + 0.212569124201, 0.206983981709, 0.201446306496, 0.195955776745, + 0.190512094256, 0.185114984406, 0.179764196185, 0.174459502324, + 0.169200699492, 0.1639876086, 0.158820075195, 0.153697969964, + 0.148621189348, 0.143589656295, 0.138603321143, 0.133662162669, + 0.128766189309, 0.123915440582, 0.119109988745, 0.114349940703, + 0.10963544023, 0.104966670533, 0.100343857232, 0.0957672718266, + 0.0912372357329, 0.0867541250127, 0.082318375932, 0.0779304915295, + 0.0735910494266, 0.0693007111742, 0.065060233529, 0.0608704821745, + 0.056732448584, 0.05264727098, 0.0486162607163, 0.0446409359769, + 0.0407230655415, 0.0368647267386, 0.0330683839378, 0.0293369977411, + 0.0256741818288, 0.0220844372634, 0.0185735200577, 0.0151490552854, + 0.0118216532614, 0.00860719483079, 0.00553245272614, 0.00265435214565 +}; + +/* tabulated values for 2^24 times x[i]/x[i+1], + * used to accept for U*x[i+1]<=x[i] without any floating point operations */ +static const unsigned long ktab[128] = +{ + 0, 12590644, 14272653, 14988939, + 15384584, 15635009, 15807561, 15933577, + 16029594, 16105155, 16166147, 16216399, + 16258508, 16294295, 16325078, 16351831, + 16375291, 16396026, 16414479, 16431002, + 16445880, 16459343, 16471578, 16482744, + 16492970, 16502368, 16511031, 16519039, + 16526459, 16533352, 16539769, 16545755, + 16551348, 16556584, 16561493, 16566101, + 16570433, 16574511, 16578353, 16581977, + 16585398, 16588629, 16591685, 16594575, + 16597311, 16599901, 16602354, 16604679, + 16606881, 16608968, 16610945, 16612818, + 16614592, 16616272, 16617861, 16619363, + 16620782, 16622121, 16623383, 16624570, + 16625685, 16626730, 16627708, 16628619, + 16629465, 16630248, 16630969, 16631628, + 16632228, 16632768, 16633248, 16633671, + 16634034, 16634340, 16634586, 16634774, + 16634903, 16634972, 16634980, 16634926, + 16634810, 16634628, 16634381, 16634066, + 16633680, 16633222, 16632688, 16632075, + 16631380, 16630598, 16629726, 16628757, + 16627686, 16626507, 16625212, 16623794, + 16622243, 16620548, 16618698, 16616679, + 16614476, 16612071, 16609444, 16606571, + 16603425, 16599973, 16596178, 16591995, + 16587369, 16582237, 16576520, 16570120, + 16562917, 16554758, 16545450, 16534739, + 16522287, 16507638, 16490152, 16468907, + 16442518, 16408804, 16364095, 16301683, + 16207738, 16047994, 15704248, 15472926 +}; + +/* tabulated values of 2^{-24}*x[i] */ +static const double wtab[128] = +{ + 1.62318314817e-08, 2.16291505214e-08, 2.54246305087e-08, 2.84579525938e-08, + 3.10340022482e-08, 3.33011726243e-08, 3.53439060345e-08, 3.72152672658e-08, + 3.8950989572e-08, 4.05763964764e-08, 4.21101548915e-08, 4.35664624904e-08, + 4.49563968336e-08, 4.62887864029e-08, 4.75707945735e-08, 4.88083237257e-08, + 5.00063025384e-08, 5.11688950428e-08, 5.22996558616e-08, 5.34016475624e-08, + 5.44775307871e-08, 5.55296344581e-08, 5.65600111659e-08, 5.75704813695e-08, + 5.85626690412e-08, 5.95380306862e-08, 6.04978791776e-08, 6.14434034901e-08, + 6.23756851626e-08, 6.32957121259e-08, 6.42043903937e-08, 6.51025540077e-08, + 6.59909735447e-08, 6.68703634341e-08, 6.77413882848e-08, 6.8604668381e-08, + 6.94607844804e-08, 7.03102820203e-08, 7.11536748229e-08, 7.1991448372e-08, + 7.2824062723e-08, 7.36519550992e-08, 7.44755422158e-08, 7.52952223703e-08, + 7.61113773308e-08, 7.69243740467e-08, 7.77345662086e-08, 7.85422956743e-08, + 7.93478937793e-08, 8.01516825471e-08, 8.09539758128e-08, 8.17550802699e-08, + 8.25552964535e-08, 8.33549196661e-08, 8.41542408569e-08, 8.49535474601e-08, + 8.57531242006e-08, 8.65532538723e-08, 8.73542180955e-08, 8.8156298059e-08, + 8.89597752521e-08, 8.97649321908e-08, 9.05720531451e-08, 9.138142487e-08, + 9.21933373471e-08, 9.30080845407e-08, 9.38259651738e-08, 9.46472835298e-08, + 9.54723502847e-08, 9.63014833769e-08, 9.71350089201e-08, 9.79732621669e-08, + 9.88165885297e-08, 9.96653446693e-08, 1.00519899658e-07, 1.0138063623e-07, + 1.02247952126e-07, 1.03122261554e-07, 1.04003996769e-07, 1.04893609795e-07, + 1.05791574313e-07, 1.06698387725e-07, 1.07614573423e-07, 1.08540683296e-07, + 1.09477300508e-07, 1.1042504257e-07, 1.11384564771e-07, 1.12356564007e-07, + 1.13341783071e-07, 1.14341015475e-07, 1.15355110887e-07, 1.16384981291e-07, + 1.17431607977e-07, 1.18496049514e-07, 1.19579450872e-07, 1.20683053909e-07, + 1.21808209468e-07, 1.2295639141e-07, 1.24129212952e-07, 1.25328445797e-07, + 1.26556042658e-07, 1.27814163916e-07, 1.29105209375e-07, 1.30431856341e-07, + 1.31797105598e-07, 1.3320433736e-07, 1.34657379914e-07, 1.36160594606e-07, + 1.37718982103e-07, 1.39338316679e-07, 1.41025317971e-07, 1.42787873535e-07, + 1.44635331499e-07, 1.4657889173e-07, 1.48632138436e-07, 1.50811780719e-07, + 1.53138707402e-07, 1.55639532047e-07, 1.58348931426e-07, 1.61313325908e-07, + 1.64596952856e-07, 1.68292495203e-07, 1.72541128694e-07, 1.77574279496e-07, + 1.83813550477e-07, 1.92166040885e-07, 2.05295471952e-07, 2.22600839893e-07 +}; + +} // namespace moose::details + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Get a Normally Distribution value from a given RNG. + * + * @tparam T + */ +/* ----------------------------------------------------------------------------*/ +template<typename T = double> +class normal_distribution +{ + +public: + + normal_distribution( T mean = 0.0, T sigma = 1.0) : + mean_(mean), sigma_(sigma) + { + mean_ = mean; + sigma_ = sigma; + } + + ~normal_distribution() { ; } + + double operator()( moose::MOOSE_RNG_DEFAULT_ENGINE& r ) + { + unsigned long U=0, sign=0, i=0, j=0; + T x=0, y=0; + + while (1) + { + U = r(); + i = U & 0x0000007F; /* 7 bit to choose the step */ + sign = U & 0x00000080; /* 1 bit for the sign */ + j = U>>8; /* 24 bit for the x-value */ + + x = j*details::wtab[i]; + if (j < details::ktab[i]) break; + + if (i<127) + { + double y0 = 0, y1 = 0; + y0 = details::ytab[i]; + y1 = details::ytab[i+1]; + y = y1+(y0-y1)*r(); + } + else + { + x = PARAM_R - std::log(1.0 - r()) / PARAM_R; + y = exp( - PARAM_R*(x-0.5* PARAM_R)) * r(); + } + if (y < std::exp(-0.5*x*x)) break; + } + return sign ? sigma_*x : -sigma_*x; + } + +public: + + T mean_; + T sigma_; +}; + +} // namespace moose + +#endif /* end of include guard: NORMALDISTRIBUTION_H */ diff --git a/moose-core/randnum/NormalRng.cpp b/moose-core/randnum/NormalRng.cpp deleted file mode 100644 index e31f636f31a900b7bed1b657d4785f3b89c9e5a9..0000000000000000000000000000000000000000 --- a/moose-core/randnum/NormalRng.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************* - * File: NormalRng.cpp - * Description: This is the MOOSE front end for class Normal, - * which generates normally distributed random - * doubles. - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-03 22:07:04 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _NORMALRNG_CPP -#define _NORMALRNG_CPP -#include "NormalRng.h" -#include "Normal.h" -const Cinfo* NormalRng::initCinfo() -{ - static ValueFinfo< NormalRng, double > mean( - "mean", - "Mean of the normal distribution", - &NormalRng::setMean, - &NormalRng::getMean); - static ValueFinfo< NormalRng, double > variance( - "variance", - "Variance of the normal distribution", - &NormalRng::setVariance, - &NormalRng::getVariance); - static ValueFinfo< NormalRng, int > method( - "method", - "Algorithm used for computing the sample. The default is 0 = alias" - " method by Ahrens and Dieter. Other options are: 1 = Box-Mueller method" - " and 2 = ziggurat method.", - &NormalRng::setMethod, - &NormalRng::getMethod); - static Finfo* normalRngFinfos[] = { - &mean, - &variance, - &method, - }; - - static string doc[] = { - "Name", "NormalRng", - "Author", "Subhasis Ray", - "Description", "Normally distributed random number generator.", - }; - Dinfo< NormalRng > dinfo; - static Cinfo normalRngCinfo( - "NormalRng", - RandGenerator::initCinfo(), - normalRngFinfos, - sizeof(normalRngFinfos)/sizeof(Finfo*), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - return &normalRngCinfo; -} - - -static const Cinfo* normalRngCinfo = NormalRng::initCinfo(); - -/** - Set the mean of the internal generator object. - */ -void NormalRng::setMean(double mean) -{ - Normal* nrng = static_cast < Normal* >(rng_); - if (nrng){ - nrng->setMean(mean); - } -} - -/** - Since normal distribution is defined in terms of mean and variance, we - want to store them in order to create the internal generator object. - */ -void NormalRng::setVariance(double variance) -{ - if ( variance < 0 ) - { - cerr << "ERROR: variance cannot be negative." << endl; - return; - } - Normal * nrng = static_cast < Normal* >(rng_); - if (nrng){ - nrng->setVariance(variance); - } -} - -/** - Returns the algorithm used. - 0 for alias method. - 1 for BoxMueller method. - */ -int NormalRng::getMethod() const -{ - Normal* nrng = static_cast < Normal * > (rng_); - if (nrng){ - return nrng->getMethod(); - } - return 0; -} -/** - Set the algorithm to be used. - 1 for BoxMueller method. - Anything else for alias method. - */ -void NormalRng::setMethod(int method) -{ - Normal* nrng = static_cast <Normal*> (rng_); - if ( nrng ){ - cout << "Warning: Changing method after generator object has been created. Current method: " << nrng->getMethod() << ". New method: " << method << endl; - nrng->setMethod((NormalGenerator)method); - } -} - -void NormalRng::vReinit(const Eref& e, ProcPtr p) -{ - // do nothing -} - -/** - By default the method used for normal distribution is alias method - by Ahrens and Dieter. In order to use some method other than the - default Alias method, one should call setMethod with a proper - method index before calling reset ( reinit ). Since different - methods create different random sequences, the combined sequence - may not have the intended distribution. By default mean and - variance are set to 0.0 and 1.0 respectively. - */ -NormalRng::NormalRng():RandGenerator() -{ - rng_ = new Normal(); -} -#endif diff --git a/moose-core/randnum/NormalRng.h b/moose-core/randnum/NormalRng.h deleted file mode 100644 index 55e100d2b4f0760541b334a80e21346fa474d3b1..0000000000000000000000000000000000000000 --- a/moose-core/randnum/NormalRng.h +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************* - * File: NormalRng.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-05 10:19:18 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _NORMALRNG_H -#define _NORMALRNG_H -#include "randnum.h" -#include "basecode/header.h" -#include "RandGenerator.h" -#include "Normal.h" - -/** - This is MOOSE wrapper for normally distributed random number generator class, Normal. - The default - */ -class NormalRng: public RandGenerator -{ - public: - NormalRng(); - virtual ~NormalRng() { ; } - void setMean(double mean); - void setVariance(double variance); - void setMethod(int method); - int getMethod() const; - virtual void vReinit( const Eref& e, ProcPtr p); - - static const Cinfo * initCinfo(); -}; - - -#endif diff --git a/moose-core/randnum/Poisson.cpp b/moose-core/randnum/Poisson.cpp deleted file mode 100644 index fe06c4e34b91b96742c17347ab4d6fd323837ca0..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Poisson.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/******************************************************************* - * File: Poisson.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-01 16:09:38 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2010 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ -/****************************************************************** - * Some of the functions have been copied/adapted from stochastic - * library package by Agner Fog, published under GPL. - * Refer to http://www.agner.org/random/ for more information. - ******************************************************************/ -#ifndef _POISSON_CPP -#define _POISSON_CPP -#include "Poisson.h" -#include "randnum.h" -#include "utility/numutil.h" -#include "Gamma.h" -#include "Binomial.h" -#include <cmath> -#include <iostream> - -using namespace std; - -Poisson::Poisson(double mean):mean_(mean), gammaGen_(NULL) //, binomialGen_(NULL) - , generator_(NULL) -{ - /* replicates setMean */ - if (mean <= 0.0) - { - cerr << "ERROR: Poisson::setMean - mean must be positive. Setting to 1.0" << endl; - mean_ = 1.0; - } - if ( mean_ < 17) - { - generator_ = Poisson::poissonSmall; - mValue_ = exp(-mean_); - } - else - { - generator_ = Poisson::poissonLarge; - mValue_ = floor(0.875*mean_); - if (gammaGen_) - { - delete gammaGen_; - } - gammaGen_ = new Gamma(mValue_, 1.0); - } -} - -Poisson::~Poisson() -{ - if (gammaGen_) - { - delete gammaGen_; - } -} - - -void Poisson::setMean(double mean) -{ - if (mean <= 0.0) - { - cerr << "ERROR: Poisson::setMean - mean must be positive. Setting to 1.0" << endl; - mean_ = 1.0; - } - if ( mean_ < 17) - { - generator_ = Poisson::poissonSmall; - mValue_ = exp(-mean_); - } - else - { - generator_ = Poisson::poissonLarge; - mValue_ = floor(0.875*mean_); - if (gammaGen_) - { - delete gammaGen_; - } - gammaGen_ = new Gamma(mValue_, 1.0); - } -} - -double Poisson::getMean() const -{ - return mean_; -} - -double Poisson::getVariance() const -{ - return mean_; -} - -double Poisson::getNextSample() const -{ - if (!generator_) - { - cerr << "ERROR: Poisson::getNextSample() - generator function is NULL" << endl; - return 0.0; - } - return generator_(*this); -} - -/** - Poisson distributed random number generator when mean is small. - See: TAOCP by Knuth, Volume 2, Section 3.4.1 - */ -double Poisson::poissonSmall(const Poisson& poisson) -{ - double product = 1.0; - - int i = 0; - while ( product > poisson.mValue_ ) - { - product *= mtrand(); - ++i; - } - return i; -} - -/** - Poisson distributed random number generator when mean is large. - See: TAOCP by Knuth, Volume 2, Section 3.4.1 - */ -/* //replaced by cleaner version - double Poisson::poissonLarge() const -{ - - // generate X with the gamma distribution of order floor(alpha*mu) - // where alpha is a suitable constant - static double m_value = floor(0.875*mean_); // alpha = 7/8 = 0.875 is a good value according to Ahrens and Dieter - static Gamma gammaGen(m_value, 1.0); - double n_value; - - double x_value = gammaGen.getNextSample(); - - if ( x_value < mean_ ) - { - Poisson poissonGen(mean_ - x_value); - n_value = m_value + poissonGen.getNextSample(); - } - else - { - Binomial binomialGen((long)m_value-1,mean_/x_value); - n_value = binomialGen.getNextSample(); - } - - return n_value; -} -*/ - // WATCH OUT: this is recursive. look for better alternative. -double Poisson::poissonLarge(const Poisson& poisson) -{ - double xValue = poisson.gammaGen_->getNextSample(); - if (xValue < poisson.mean_) - { - Poisson poissonGen(poisson.mean_ - xValue); - return poisson.mValue_ + poissonGen.getNextSample(); - } - Binomial binomialGen((long)poisson.mValue_ - 1, poisson.mean_/xValue); - return binomialGen.getNextSample(); -} - -#ifdef TEST_MAIN - -#include <vector> -#include <algorithm> -#include <cstdlib> -int main(int argc, char **argv) -{ - double mean = 4; - - if (argc > 1) - mean = atof(argv[1]); - - - double sum = 0.0; - double sd = 0.0; - vector <double> samples; - Poisson poisson(mean); - int MAX_SAMPLE = 100000; - unsigned index; - - - cout << "epsilon = " << getMachineEpsilon() << endl; - for ( int i = 0; i < MAX_SAMPLE; ++i ) - { - double p = poisson.getNextSample();//aliasMethod(); - samples.push_back(p); - - sum += p; - sd += (p - mean)*(p - mean); - } - mean = sum/MAX_SAMPLE; - sd = sqrt(sd/MAX_SAMPLE); - cout << "mean = " << mean << " sd = " << sd << endl; - sort(samples.begin(), samples.end()); - - unsigned i = 0; - unsigned start = 0; - index = 0; - - while ( i < samples.size() ) - { - int count = 0; - - while( ( i < samples.size() ) && (samples[i] == samples[start] )) - { - ++count; - ++i; - } - while( index < samples[start]) - { - cout << index++ << " " << 0 << endl; - } - - cout << index++ << " " << count << endl; - start = i; - } - return 0; -} -#endif // test main -#endif diff --git a/moose-core/randnum/Poisson.h b/moose-core/randnum/Poisson.h deleted file mode 100644 index 985bd56f56693bc3991bbf9e8967348acec326a0..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Poisson.h +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************* - * File: Poisson.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-02 09:43:47 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _POISSON_H -#define _POISSON_H - -#include "Probability.h" -#include "Gamma.h" -#include "Binomial.h" - -class Poisson; - -typedef double (Poisson::*PoissonGenerator)() const; - -#define CALL_POSSON_GENERATOR(object,ptrToMember) ((object).*(ptrToMember)) - -class Poisson:public Probability -{ - public: - Poisson(double mean=1.0); - ~Poisson(); - - void setMean(double mean); - double getMean() const; - double getVariance() const; - double getNextSample() const; - private: - double mean_; - static double poissonSmall(const Poisson&); - static double poissonLarge(const Poisson&); - Gamma* gammaGen_; - //Binomial* binomialGen_; - double (*generator_)(const Poisson&); - double mValue_; -}; - -#endif diff --git a/moose-core/randnum/PoissonRng.cpp b/moose-core/randnum/PoissonRng.cpp deleted file mode 100644 index b8ac5b5c140730fe859b41c3ad8464e88eef9ba1..0000000000000000000000000000000000000000 --- a/moose-core/randnum/PoissonRng.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************* - * File: PoissonRng.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-08 09:53:32 - * Updated: 2014-09-29 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _POISSONRNG_CPP -#define _POISSONRNG_CPP -#include "../basecode/header.h" -#include "PoissonRng.h" - -const Cinfo* PoissonRng::initCinfo() -{ - static ValueFinfo< PoissonRng, double > mean( - "mean", - "Mean of the Poisson distribution.", - &PoissonRng::setMean, - &PoissonRng::getMean); - static Finfo* poissonRngFinfos[] = { - &mean, - }; - static string doc[] = { - "Name", "PoissonRng", - "Author", "Subhasis Ray", - "Description", "Poisson distributed random number generator.", - }; - static Dinfo< PoissonRng > dinfo; - static Cinfo poissonRngCinfo( - "PoissonRng", - RandGenerator::initCinfo(), - poissonRngFinfos, - sizeof(poissonRngFinfos)/sizeof(Finfo*), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - - return &poissonRngCinfo; -} - - -static const Cinfo* poissonRngCinfo = PoissonRng::initCinfo(); - -PoissonRng::PoissonRng() -{ - //do nothing. should not try to get mean -} - -/** - Sets the mean. Since poisson distribution is defined in terms of - the rate parameter or the mean, it is mandatory to set this before - using the generator. -*/ -void PoissonRng::setMean(double mean) -{ - Poisson * prng = static_cast<Poisson*>(rng_); - if ( !prng ){ - rng_ = new Poisson(mean); - } else { - prng->setMean(mean); - } -} -/** - reports error in case the parameter mean has not been set. -*/ -void PoissonRng::vReinit(const Eref& e, ProcPtr p) -{ - if ( !rng_ ) - { - cerr << "ERROR: PoissonRng::vReinit - mean must be set before using the Poisson distribution generator." << endl; - } -} - - -#endif diff --git a/moose-core/randnum/PoissonRng.h b/moose-core/randnum/PoissonRng.h deleted file mode 100644 index 119276b750d04b58700a161cfb78ca1e2cd1f37b..0000000000000000000000000000000000000000 --- a/moose-core/randnum/PoissonRng.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************* - * File: PoissonRng.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-07 16:22:35 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _POISSONRNG_H -#define _POISSONRNG_H -#include "Poisson.h" -#include "RandGenerator.h" -class PoissonRng:public RandGenerator -{ - public: - PoissonRng(); - virtual ~PoissonRng() { ; } - void setMean(double mean); - virtual void vReinit(const Eref& e, ProcPtr p); - static const Cinfo * initCinfo(); -}; - - -#endif diff --git a/moose-core/randnum/Probability.cpp b/moose-core/randnum/Probability.cpp deleted file mode 100644 index c7ad7da78c116b8e505ef465186bfb1480e0ed03..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Probability.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************* - * File: Probability.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-10-28 13:35:39 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _PROBABILITY_CPP -#define _PROBABILITY_CPP -#include "Probability.h" - -//const Cinfo* initProbabilityCinfo -// TODO: implement some tests for generated distributions -// Kolmogorov-Smirnov test in particular - -#endif diff --git a/moose-core/randnum/Probability.h b/moose-core/randnum/Probability.h deleted file mode 100644 index 61c5acf5d5ad1c2488949b5e6c3977f3210f0719..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Probability.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************* - * File: Probability.h - * Description: This is base class for various probability - * distribution generator classes. - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-10-28 13:30:41 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _PROBABILITY_H -#define _PROBABILITY_H - - -/** - Base class for implementing various probability distributions. - */ -class Probability -{ - public: - virtual ~Probability(){}; - - virtual double getMean() const =0; - virtual double getVariance()const =0; - virtual double getNextSample()const =0; - - private: -// long double mean_; // TODO : do we really need this? -// long double variance_;// TODO : do we really need this? -}; - -#endif diff --git a/moose-core/randnum/RNG.h b/moose-core/randnum/RNG.h index 9eb1639ec093dd4088d20aea500155f38a74d0ff..758e599ba4ea21f666607e2a0d54bfed1f635e30 100644 --- a/moose-core/randnum/RNG.h +++ b/moose-core/randnum/RNG.h @@ -19,29 +19,17 @@ #ifndef __RNG_INC #define __RNG_INC -#ifdef USE_BOOST - -#include <boost/random.hpp> -#include <boost/random/uniform_01.hpp> - -#if defined(BOOST_RANDOM_DEVICE_EXISTS) -#include <boost/random/random_device.hpp> -#endif // BOOST_RANDOM_DEVICE_EXISTS -#else /* ----- not USE_BOOST ----- */ -#include <ctime> -#include "randnum.h" -#endif /* ----- not USE_BOOST ----- */ - #include <limits> #include <iostream> - -#ifdef ENABLE_CPP11 #include <random> -#endif + +#include "Definitions.h" +#include "Distributions.h" using namespace std; -namespace moose { +namespace moose +{ /* * ===================================================================================== @@ -65,17 +53,8 @@ class RNG void setRandomSeed( ) { -#if defined(USE_BOOST) -#if defined(BOOST_RANDOM_DEVICE_EXISTS) - boost::random::random_device rd; - setSeed( rd() ); -#endif -#elif defined(ENABLE_CPP11) - std::random_device rd; - setSeed( rd() ); -#else - mtseed( time(NULL) ); -#endif /* ----- not ENABLE_CPP11 ----- */ + MOOSE_RANDOM_DEVICE rd_; + setSeed( rd_() ); } /* ==================== ACCESSORS ======================================= */ @@ -91,20 +70,15 @@ class RNG * * @param seed */ - void setSeed( const unsigned long int seed ) + void setSeed( const unsigned long seed ) { seed_ = seed; if( seed == 0 ) { - setRandomSeed( ); - return; + MOOSE_RANDOM_DEVICE rd_; + seed_ = rd_(); } - -#if defined(USE_BOOST) || defined(ENABLE_CPP11) rng_.seed( seed_ ); -#else - mtseed( seed_ ); -#endif } /** @@ -115,11 +89,7 @@ class RNG */ T uniform( const T a, const T b) { -#if defined(USE_BOOST) || defined(ENABLE_CPP11) return ( b - a ) * dist_( rng_ ) + a; -#else - return (b-a) * mtrand() + a; -#endif } /** @@ -130,11 +100,7 @@ class RNG */ T uniform( void ) { -#if defined(USE_BOOST) || defined(ENABLE_CPP11) return dist_( rng_ ); -#else - return mtrand(); -#endif } @@ -143,17 +109,11 @@ class RNG T res_; T seed_; -#if USE_BOOST - boost::random::mt19937 rng_; - boost::random::uniform_01<T> dist_; -#elif ENABLE_CPP11 - std::mt19937 rng_; - std::uniform_real_distribution<> dist_; -#endif /* ----- not ENABLE_CPP11 ----- */ + moose::MOOSE_RNG_DEFAULT_ENGINE rng_; + moose::MOOSE_UNIFORM_DISTRIBUTION<double> dist_; }; /* ----- end of template class RNG ----- */ - } /* namespace moose ends */ #endif /* ----- #ifndef __RNG_INC ----- */ diff --git a/moose-core/randnum/RandGenerator.cpp b/moose-core/randnum/RandGenerator.cpp deleted file mode 100644 index 7bd80f355fc4528866de305a6a746c249a06f0e2..0000000000000000000000000000000000000000 --- a/moose-core/randnum/RandGenerator.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/******************************************************************* - * File: RandGenerator.cpp - * Description: Interface class for MOOSE to access various - * random number generator. - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-03 21:48:17 - ********************************************************************/ -/********************************************************************** - ** This program is part of 'MOOSE', the - ** Messaging Object Oriented Simulation Environment, - ** also known as GENESIS 3 base code. - ** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS - ** It is made available under the terms of the - ** GNU General Public License version 2 - ** See the file COPYING.LIB for the full notice. - **********************************************************************/ - -#ifndef _RANDGENERATOR_CPP -#define _RANDGENERATOR_CPP - -#include "../basecode/header.h" -#include "RandGenerator.h" - -static SrcFinfo1< double >* output() -{ - static SrcFinfo1< double > output( - "output", - "Generated random number."); - return &output; -} - -const Cinfo * RandGenerator::initCinfo() -{ - ////////////////////////////////////////////////////////////// - // MsgDest Definitions - ////////////////////////////////////////////////////////////// - static DestFinfo process( - "process", - "Handles process call, updates internal time stamp.", - new ProcOpFunc< RandGenerator >( &RandGenerator::process )); - static DestFinfo reinit( - "reinit", - "Handles reinit call.", - new ProcOpFunc< RandGenerator >( &RandGenerator::reinit )); - ////////////////////////////////////////////////////////////// - // SharedMsg Definitions - ////////////////////////////////////////////////////////////// - static Finfo* procShared[] = { - &process, &reinit - }; - static SharedFinfo proc( - "proc", - "Shared message for process and reinit", - procShared, sizeof( procShared ) / sizeof( const Finfo* )); - - ////////////////////////////////////////////////////////////// - // ValueFinfo Definitions - ////////////////////////////////////////////////////////////// - - static ReadOnlyValueFinfo<RandGenerator, double> sample( - "sample", - "Generated pseudorandom number.", - &RandGenerator::getSample); - static ReadOnlyValueFinfo< RandGenerator, double > mean( - "mean", - "Mean of the distribution.", - &RandGenerator::getMean); - static ReadOnlyValueFinfo<RandGenerator, double> variance( - "variance", - "Variance of the distribution.", - &RandGenerator::getVariance); - - static Finfo * randGeneratorFinfos[] = { - &sample, - &mean, - &variance, - output(), - &proc, - }; - - static string doc[] = { - "Name", "RandGenerator", - "Author", "Subhasis Ray", - "Description", "Base class for random number generators for sampling various" - " probability distributions. This class should not be used" - " directly. Instead, its subclasses named after specific distributions" - " should be used.", - }; - - static Dinfo< RandGenerator > dinfo; - static Cinfo randGeneratorCinfo( - "RandGenerator", - Neutral::initCinfo(), - randGeneratorFinfos, - sizeof(randGeneratorFinfos)/sizeof(Finfo*), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - - return &randGeneratorCinfo; -} - -static const Cinfo * randGeneratorCinfo = RandGenerator::initCinfo(); - -RandGenerator::RandGenerator() -{ - sample_ = 0.0; - rng_ = NULL; -} - -RandGenerator::~RandGenerator() -{ - if (rng_) - { - delete rng_; - rng_ = NULL; - } -} - -double RandGenerator::getMean() const -{ - if (rng_) - { - return rng_->getMean(); - } - return 0.0; -} - -double RandGenerator::getVariance() const -{ - if (rng_) - { - return rng_->getVariance(); - } - return 0.0; -} - -double RandGenerator::getSample() const -{ - return sample_; -} - -void RandGenerator::process( const Eref& e, ProcPtr p ) -{ - if (rng_){ - sample_ = rng_->getNextSample(); - output()->send(e, sample_); - } -} - -void RandGenerator::reinit(const Eref& e, ProcPtr p) -{ - vReinit(e, p); -} - -void RandGenerator::vReinit(const Eref& e, ProcPtr p) -{ - cerr << "RandGenerator::vReinit() - this function should never be reached. Guilty party: " << e.id().path() << endl; -} - -#endif diff --git a/moose-core/randnum/RandGenerator.h b/moose-core/randnum/RandGenerator.h deleted file mode 100644 index 7e37b716ceabce763c2573e80a2611583a414cc2..0000000000000000000000000000000000000000 --- a/moose-core/randnum/RandGenerator.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************* - * File: RandGenerator.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2007-11-07 16:25:08 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _RANDGENERATOR_H -#define _RANDGENERATOR_H - -#include "randnum.h" -#include "basecode/header.h" -#include "Probability.h" - -/** - This class is a moose interface to underlying random number - generators (which is an instance of Probability class). - */ -class RandGenerator -{ - public: - RandGenerator(); - virtual ~RandGenerator(); - double getMean() const; - double getVariance() const; - double getSample() const; - void process( const Eref& e, ProcPtr info); - void reinit( const Eref& e, ProcPtr info); - virtual void vReinit( const Eref& e, ProcPtr info); - - static const Cinfo * initCinfo(); - protected: - Probability* rng_; - double sample_; -}; - - -#endif diff --git a/moose-core/randnum/Uniform.cpp b/moose-core/randnum/Uniform.cpp deleted file mode 100644 index 1b9fb8bf9f6fdca4c453bf7dae42a018a63b4695..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Uniform.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************* - * File: Uniform.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2008-02-21 17:12:55 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _UNIFORM_CPP -#define _UNIFORM_CPP - -#include <cassert> -#include <iostream> -#include <vector> - -#include "Uniform.h" -#include "randnum.h" -#include "utility/numutil.h" -using namespace std; - -Uniform::Uniform() -{ - min_ = 0.0; - max_ = 1.0; -} -Uniform::Uniform(double min, double max) -{ - if ( min >= max ) - { - cerr << "ERROR: specified lowerbound is greater than upper bound." << endl; - min_ = 0.0; - max_ = 1.0; - return; - } - - min_ = min; - max_ = max; -} -double Uniform::getMean() const -{ - return (max_ + min_) / 2.0; -} -double Uniform::getVariance()const -{ - return (max_- min_) * (max_ - min_)/12.0; -} -double Uniform::getMin() const -{ - return min_; -} -double Uniform::getMax() const -{ - return max_; -} -void Uniform::setMin(double min) -{ - min_ = min; -} -void Uniform::setMax(double max) -{ - max_ = max; -} -double Uniform::getNextSample() const -{ - assert( max_ > min_ ); - return mtrand()*(max_-min_)+min_; -} - -#ifdef DO_UNIT_TESTS -void doTest(double min, double max, unsigned count) -{ - Uniform rng; - - rng.setMin(min); - rng.setMax(max); - assert(isClose<double>(min, rng.getMin(), DBL_EPSILON)); - assert(isClose<double>(max, rng.getMax(), DBL_EPSILON)); - vector <double> seq; - double mean = 0.0; - - - for (unsigned ii = 0; ii < count; ++ii ) - { - double sample; - sample = rng.getNextSample(); - mean += sample; - seq.push_back(sample); - } - mean /= count; - double var = 0.0; - for(unsigned ii = 0; ii <seq.size(); ++ii) - { - var += (mean - seq[ii]) * (mean - seq[ii]); - } - var = var / count; - cout << "theoretical mean: " << rng.getMean() << ", sample mean: " << mean << ", theoretical var: " << rng.getVariance() << ", sample var: " << var << ", sample size: " << count << endl; - -} - -void testUniform() -{ - cout << "testUniform(): testing uniform rng.\n"; - doTest(-10.0, 10.0, 1000); - doTest(1e-10, 1.1e-10, 1000); -} - -#endif // DO_UNIT_TESTS -#if defined( TEST_MAIN ) && defined(DO_UNIT_TESTS) -int main(void) -{ - testUniform(); -} - -#endif // !defined( TEST_MAIN ) && defined(DO_UNIT_TESTS) - -#endif diff --git a/moose-core/randnum/Uniform.h b/moose-core/randnum/Uniform.h deleted file mode 100644 index 3073fb8252578b8f20424682fd76710d3c5f414d..0000000000000000000000000000000000000000 --- a/moose-core/randnum/Uniform.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************* - * File: Uniform.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2008-02-21 17:09:54 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _UNIFORM_H -#define _UNIFORM_H - -#include "Probability.h" - -class Uniform: public Probability -{ - public: - Uniform(); - Uniform(double min, double max); - double getMean() const; - double getVariance() const; - double getNextSample() const; - double getMin() const; - double getMax() const; - void setMin(double min); - void setMax(double max); - - private: - double min_; - double max_; - -}; - - -#endif diff --git a/moose-core/randnum/UniformRng.cpp b/moose-core/randnum/UniformRng.cpp deleted file mode 100644 index 15630b7c459fb28404b4d043c1a6f31cf212ac97..0000000000000000000000000000000000000000 --- a/moose-core/randnum/UniformRng.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************* - * File: UniformRng.cpp - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2008-02-01 11:30:20 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _UNIFORMRNG_CPP -#define _UNIFORMRNG_CPP -#include "../basecode/header.h" -#include "randnum.h" -#include "UniformRng.h" -#include "Uniform.h" - -const Cinfo* UniformRng::initCinfo() -{ - static ValueFinfo< UniformRng, double > min( - "min", - "The lower bound on the numbers generated ", - &UniformRng::setMin, - &UniformRng::getMin); - static ValueFinfo< UniformRng, double > max( - "max", - "The upper bound on the numbers generated", - &UniformRng::setMax, - &UniformRng::getMax); - - static Finfo * uniformRngFinfos[] = { - &min, - &max, - }; - static string doc[] = - { - "Name", "UniformRng", - "Author", "Subhasis Ray", - "Description", "Generates pseudorandom number from a unform distribution.", - }; - static Dinfo< UniformRng > dinfo; - static Cinfo uniformRngCinfo( - "UniformRng", - RandGenerator::initCinfo(), - uniformRngFinfos, - sizeof( uniformRngFinfos ) / sizeof( Finfo* ), - &dinfo, - doc, - sizeof( doc ) / sizeof( string )); - return &uniformRngCinfo; -} - -static const Cinfo* uniformRngCinfo = UniformRng::initCinfo(); - -double UniformRng::getMin()const -{ - Uniform * urng = static_cast< Uniform * >(rng_); - if (urng){ - return urng->getMin(); - } - return 0.0; -} - -double UniformRng::getMax() const -{ - Uniform * urng = static_cast< Uniform * >(rng_); - if (urng){ - return urng->getMax(); - } - return 0.0; -} - -void UniformRng::setMin(double min) -{ - Uniform * urng = static_cast<Uniform *> (rng_); - if (urng){ - urng->setMin(min); - } -} - -void UniformRng::setMax(double max) -{ - Uniform * urng = static_cast<Uniform *> (rng_); - if (urng){ - urng->setMax(max); - } -} - -UniformRng::UniformRng():RandGenerator() -{ - rng_ = new Uniform(); -} - -void UniformRng::vReinit(const Eref& e, ProcPtr p) -{ - ; /* no use */ -} - -#ifdef DO_UNIT_TESTS -void testUniformRng() -{ - cout << "testUniformRng(): yet to be implemented" << endl; -} - -#endif -#endif diff --git a/moose-core/randnum/UniformRng.h b/moose-core/randnum/UniformRng.h deleted file mode 100644 index da4d4af07952f84606e0564044300a30f112c8c6..0000000000000000000000000000000000000000 --- a/moose-core/randnum/UniformRng.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************* - * File: UniformRng.h - * Description: - * Author: Subhasis Ray - * E-mail: ray.subhasis@gmail.com - * Created: 2008-02-01 11:52:48 - ********************************************************************/ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** also known as GENESIS 3 base code. -** copyright (C) 2003-2005 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU General Public License version 2 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _UNIFORMRNG_H -#define _UNIFORMRNG_H - -#include "randnum.h" -#include "RandGenerator.h" - -class UniformRng: public RandGenerator -{ - public: - UniformRng(); - virtual ~UniformRng() { ; } - double getMin() const; - double getMax() const; - void setMin(double min); - void setMax(double max); - virtual void vReinit(const Eref& e, ProcPtr p); - - static const Cinfo * initCinfo(); - private: - double min_; - double max_; -}; - - - -#endif diff --git a/moose-core/randnum/mt19937ar.cpp b/moose-core/randnum/mt19937ar.cpp deleted file mode 100644 index 3becb14a9a1aa52b9e7e0ea1e7fd706129ed57d8..0000000000000000000000000000000000000000 --- a/moose-core/randnum/mt19937ar.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -*/ - -/* Modified slightly for use in MOOSE by Upi Bhalla, NCBS, 2004 */ -#ifdef _WIN32 -#include <Winsock2.h> -#else -#define _BSD_SOURCE -#include <sys/time.h> -#endif -#include <stdlib.h> -#include "randnum.h" -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ - -static unsigned long mt[N]; /* the array for the state vector */ -static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ - -/* initializes mt[N] with a seed */ -void init_genrand(unsigned long s) -{ - mt[0]= s & 0xffffffffUL; - for (mti=1; mti<N; mti++) { - mt[mti] = - (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffUL; - /* for >32 bit machines */ - } -} - -//Add code for gettimeofday -#ifdef _WIN32 - int gettimeofday( struct timeval* tv, void* timezone ) { - FILETIME time; - double timed; - - GetSystemTimeAsFileTime( &time ); - - // Apparently Win32 has units of 1e-7 sec (tenths of microsecs) - // 4294967296 is 2^32, to shift high word over - // 11644473600 is the number of seconds between - // the Win32 epoch 1601-Jan-01 and the Unix epoch 1970-Jan-01 - // Tests found floating point to be 10x faster than 64bit int math. - - timed = ((time.dwHighDateTime * 4294967296e-7) - 11644473600.0) + - (time.dwLowDateTime * 1e-7); - - tv->tv_sec = (long) timed; - tv->tv_usec = (long) ((timed - tv->tv_sec) * 1e6); - - return 0; - } -#endif - - - - - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(long int init_key[], int key_length) -{ - int i, j, k; - init_genrand(19650218UL); - i=1; j=0; - k = (N>key_length ? N : key_length); - for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) - + init_key[j] + j; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - if (j>=key_length) j=0; - } - for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - - i; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - } - - mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ -} - -/* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void) -{ - unsigned long y; - static unsigned long mag01[2]={0x0UL, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489UL); /* a default initial seed is used */ - - for (kk=0;kk<N-M;kk++) { - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); - mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - for (;kk<N-1;kk++) { - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); - mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} -#if 0 -/* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void) -{ - return (long)(genrand_int32()>>1); -} - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void) -{ - return genrand_int32()*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void) -{ - return genrand_int32()*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void) -{ - return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void) -{ - unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} -/* These real versions are due to Isaku Wada, 2002/01/09 added */ - -/* -int main(void) -{ - int i; - unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4; - init_by_array(init, length); - printf("1000 outputs of genrand_int32()\n"); - for (i=0; i<1000; i++) { - printf("%10lu ", genrand_int32()); - if (i%5==4) printf("\n"); - } - printf("\n1000 outputs of genrand_real2()\n"); - for (i=0; i<1000; i++) { - printf("%10.8f ", genrand_real2()); - if (i%5==4) printf("\n"); - } - return 0; -} -*/ -#endif - -void mtseed(long seed = 0) -{ - struct timeval tv; - - if (seed == 0) { - char* hostname = getenv("HOST"); - gettimeofday(&tv, NULL); - if (hostname != NULL) { - for (int i = 0; *hostname; hostname++, i++){ - tv.tv_usec += *hostname * i * i * 16; - } - } - long int init[2] = {tv.tv_sec, tv.tv_usec}; - long int length = 2; - init_by_array(init, length); - } else { - // unsigned long init[1] = {seed}; - // unsigned long length = 1; - // init_by_array(init, length); - init_genrand( seed ); - } -} - -/* generates a random number on [0,1)-real-interval */ -double mtrand(void) -{ - return genrand_int32()*(1.0/4294967296.0); - /* divided by 2^32 */ -} diff --git a/moose-core/randnum/randnum.h b/moose-core/randnum/randnum.h deleted file mode 100644 index 5af4abda3b2cb0ba70c9b38f5d0b42ffabd65af8..0000000000000000000000000000000000000000 --- a/moose-core/randnum/randnum.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment, -** copyright (C) 2003-2004 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU Lesser General Public License version 2.1 -** See the file COPYING.LIB for the full notice. -** Development of this software was supported by -** Biophase Simulations Inc, http://www.bpsims.com -** See the file BIOPHASE.INFO for details. -**********************************************************************/ -extern double mtrand(void); -extern void mtseed(long seed); -extern unsigned long genrand_int32(void); - diff --git a/moose-core/randnum/test_normal_dist.cpp b/moose-core/randnum/test_normal_dist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..101a54546532a9e05f211aef054b94e601ea88ad --- /dev/null +++ b/moose-core/randnum/test_normal_dist.cpp @@ -0,0 +1,63 @@ +/*** + * Filename: test_normal_dist.cpp + * + * Description: test script. + * + * Version: 0.0.1 + * Created: 2018-08-04 + + * Revision: none + * + * Author: Dilawar Singh <dilawars@ncbs.res.in> + * Organization: NCBS Bangalore + * + * License: GNU GPL2 + */ + + +#include <iostream> +#include <map> +#include <iomanip> + +#include "Distributions.h" +#include "../utility/testing_macros.hpp" + + +int test_normal_dist( ) +{ + + moose::MOOSE_RANDOM_DEVICE rd; + moose::MOOSE_RNG_DEFAULT_ENGINE gen; + gen.seed( 10 ); + + moose::MOOSE_NORMAL_DISTRIBUTION<double> d(0, 1); + + std::map<int, int> hist{}; + std::vector<double> dist; + for(int n=0; n<100000; ++n) + { + double x = d(gen); + dist.push_back( x ); + ++hist[ std::round(x) ]; + } + + for(auto p : hist) { + std::cout << std::setw(2) + << p.first << ' ' << std::string(p.second/200, '*') << '\n'; + } + + ASSERT_DOUBLE_EQ( "NORMALDIST", hist[-3], 542 ); + ASSERT_DOUBLE_EQ( "NORMALDIST", hist[-2], 5987 ); + ASSERT_DOUBLE_EQ( "NORMALDIST", hist[-1], 24262 ); + ASSERT_DOUBLE_EQ( "NORMALDIST", hist[0], 38236 ); + ASSERT_DOUBLE_EQ( "NORMALDIST", hist[1], 24386 ); + ASSERT_DOUBLE_EQ( "NORMALDIST", hist[2], 6071 ); + + return 0; +} + +int main(int argc, const char *argv[]) +{ + test_normal_dist(); + return 0; +} diff --git a/moose-core/scheduling/Clock.cpp b/moose-core/scheduling/Clock.cpp index dc45989f3a781825554bb42f8958fc98a251f3c1..aad5c0666fa608e09e53c7ce1de7e4b69a297354 100644 --- a/moose-core/scheduling/Clock.cpp +++ b/moose-core/scheduling/Clock.cpp @@ -30,25 +30,25 @@ * * The system works like this: * 1. Assign times to each Tick. This is divided by dt_ and the rounded - * value is used for the integral multiple. Zero means the tick is not - * scheduled. + * value is used for the integral multiple. Zero means the tick is not + * scheduled. * 2. The process call goes through all active ticks in order every - * timestep. Each Tick increments its counter and decides if it is - * time to fire. + * timestep. Each Tick increments its counter and decides if it is + * time to fire. * 4. The Reinit call goes through all active ticks in order, just once. * 5. We connect up the Ticks to their target objects. * 6. We begin the simulation by calling 'start' or 'step' on the Clock. - * 'step' executes exactly one timestep (of the minimum dt_), - * visiting all ticks as above.. - * 'start' executes an integral number of such timesteps. + * 'step' executes exactly one timestep (of the minimum dt_), + * visiting all ticks as above.. + * 'start' executes an integral number of such timesteps. * 7. To interrupt the simulation at some intermediate time, call 'stop'. - * This lets the system complete its current step. + * This lets the system complete its current step. * 8. To restart the simulation from where it left off, use the same - * 'start' or 'step' function on the Clock. As all the ticks - * retain their state, the simulation can resume smoothly. + * 'start' or 'step' function on the Clock. As all the ticks + * retain their state, the simulation can resume smoothly. */ -#include "header.h" +#include "../basecode/header.h" #include "Clock.h" #include "../utility/numutil.h" #include "../utility/print_function.hpp" @@ -259,52 +259,52 @@ const Cinfo* Clock::initCinfo() static Finfo* clockFinfos[] = { // Fields - &dt, // Value - &runTime, // ReadOnlyValue - ¤tTime, // ReadOnlyValue - &nsteps, // ReadOnlyValue - &numTicks, // ReadOnlyValue - &stride, // ReadOnlyValue - ¤tStep, // ReadOnlyValue - &dts, // ReadOnlyValue - &isRunning, // ReadOnlyValue - &tickStep, // LookupValue - &tickDt, // LookupValue - &defaultTick, // ReadOnlyLookupValue - &clockControl, // Shared - finished(), // Src - procs[0], // Src - procs[1], // Src - procs[2], // Src - procs[3], // Src - procs[4], // Src - procs[5], // Src - procs[6], // Src - procs[7], // Src - procs[8], // Src - procs[9], // Src - procs[10], // Src - procs[11], // Src - procs[12], // Src - procs[13], // Src - procs[14], // Src - procs[15], // Src - procs[16], // Src - procs[17], // Src - procs[18], // Src - procs[19], // Src - procs[20], // Src - procs[21], // Src - procs[22], // Src - procs[23], // Src - procs[24], // Src - procs[25], // Src - procs[26], // Src - procs[27], // Src - procs[28], // Src - procs[29], // Src - procs[30], // Src - procs[31], // Src + &dt, // Value + &runTime, // ReadOnlyValue + ¤tTime, // ReadOnlyValue + &nsteps, // ReadOnlyValue + &numTicks, // ReadOnlyValue + &stride, // ReadOnlyValue + ¤tStep, // ReadOnlyValue + &dts, // ReadOnlyValue + &isRunning, // ReadOnlyValue + &tickStep, // LookupValue + &tickDt, // LookupValue + &defaultTick, // ReadOnlyLookupValue + &clockControl, // Shared + finished(), // Src + procs[0], // Src + procs[1], // Src + procs[2], // Src + procs[3], // Src + procs[4], // Src + procs[5], // Src + procs[6], // Src + procs[7], // Src + procs[8], // Src + procs[9], // Src + procs[10], // Src + procs[11], // Src + procs[12], // Src + procs[13], // Src + procs[14], // Src + procs[15], // Src + procs[16], // Src + procs[17], // Src + procs[18], // Src + procs[19], // Src + procs[20], // Src + procs[21], // Src + procs[22], // Src + procs[23], // Src + procs[24], // Src + procs[25], // Src + procs[26], // Src + procs[27], // Src + procs[28], // Src + procs[29], // Src + procs[30], // Src + procs[31], // Src }; static string doc[] = @@ -360,79 +360,79 @@ const Cinfo* Clock::initCinfo() " STDPSynHandler 1 50e-6\n" " GraupnerBrunel2012CaPlasticitySynHandler 1 50e-6\n" " SeqSynHandler 1 50e-6\n" - " CaConc 1 50e-6\n" - " CaConcBase 1 50e-6\n" - " DifShell 1 50e-6\n" - " DifShellBase 1 50e-6\n" - " MMPump 1 50e-6\n" - " DifBuffer 1 50e-6\n" - " DifBufferBase 1 50e-6\n" - " MgBlock 1 50e-6\n" - " Nernst 1 50e-6\n" - " RandSpike 1 50e-6\n" - " ChanBase 2 50e-6\n" - " IntFire 2 50e-6\n" - " IntFireBase 2 50e-6\n" - " LIF 2 50e-6\n" - " QIF 2 50e-6\n" - " ExIF 2 50e-6\n" - " AdExIF 2 50e-6\n" - " AdThreshIF 2 50e-6\n" - " IzhIF 2 50e-6\n" - " IzhikevichNrn 2 50e-6\n" - " SynChan 2 50e-6\n" - " NMDAChan 2 50e-6\n" - " GapJunction 2 50e-6\n" - " HHChannel 2 50e-6\n" - " HHChannel2D 2 50e-6\n" - " Leakage 2 50e-6\n" - " MarkovChannel 2 50e-6\n" - " MarkovGslSolver 2 50e-6\n" - " MarkovRateTable 2 50e-6\n" - " MarkovSolver 2 50e-6\n" - " MarkovSolverBase 2 50e-6\n" - " RC 2 50e-6\n" - " Compartment (init) 3 50e-6\n" - " CompartmentBase (init ) 3 50e-6\n" - " SymCompartment (init) 3 50e-6\n" - " Compartment 4 50e-6\n" - " CompartmentBase 4 50e-6\n" - " SymCompartment 4 50e-6\n" - " SpikeGen 5 50e-6\n" - " HSolve 6 50e-6\n" - " SpikeStats 7 50e-6\n" - " Table 8 0.1e-3\n" - " TimeTable 8 0.1e-3\n" - - " Dsolve 10 0.01\n" - " Adaptor 11 0.1\n" - " Func 12 0.1\n" - " Function 12 0.1\n" - " Arith 12 0.1\n" - " BufPool 13 0.1\n" - " Pool 13 0.1\n" - " PoolBase 13 0.1\n" - " CplxEnzBase 14 0.1\n" - " Enz 14 0.1\n" - " EnzBase 14 0.1\n" - " MMenz 14 0.1\n" - " Reac 14 0.1\n" - " ReacBase 14 0.1\n" - " Gsolve (init) 15 0.1\n" - " Ksolve (init) 15 0.1\n" - " Gsolve 16 0.1\n" - " Ksolve 16 0.1\n" - " Stats 17 0.1\n" - " Table2 18 1\n" - " Streamer 19 10\n" - - " HDF5DataWriter 30 1\n" - " HDF5WriterBase 30 1\n" - " NSDFWriter 30 1\n" - " PyRun 30 1\n" - " PostMaster 31 0.01\n" - " \n" - " Note that the other classes are not scheduled at all.", + " CaConc 1 50e-6\n" + " CaConcBase 1 50e-6\n" + " DifShell 1 50e-6\n" + " DifShellBase 1 50e-6\n" + " MMPump 1 50e-6\n" + " DifBuffer 1 50e-6\n" + " DifBufferBase 1 50e-6\n" + " MgBlock 1 50e-6\n" + " Nernst 1 50e-6\n" + " RandSpike 1 50e-6\n" + " ChanBase 2 50e-6\n" + " IntFire 2 50e-6\n" + " IntFireBase 2 50e-6\n" + " LIF 2 50e-6\n" + " QIF 2 50e-6\n" + " ExIF 2 50e-6\n" + " AdExIF 2 50e-6\n" + " AdThreshIF 2 50e-6\n" + " IzhIF 2 50e-6\n" + " IzhikevichNrn 2 50e-6\n" + " SynChan 2 50e-6\n" + " NMDAChan 2 50e-6\n" + " GapJunction 2 50e-6\n" + " HHChannel 2 50e-6\n" + " HHChannel2D 2 50e-6\n" + " Leakage 2 50e-6\n" + " MarkovChannel 2 50e-6\n" + " MarkovGslSolver 2 50e-6\n" + " MarkovRateTable 2 50e-6\n" + " MarkovSolver 2 50e-6\n" + " MarkovSolverBase 2 50e-6\n" + " RC 2 50e-6\n" + " Compartment (init) 3 50e-6\n" + " CompartmentBase (init ) 3 50e-6\n" + " SymCompartment (init) 3 50e-6\n" + " Compartment 4 50e-6\n" + " CompartmentBase 4 50e-6\n" + " SymCompartment 4 50e-6\n" + " SpikeGen 5 50e-6\n" + " HSolve 6 50e-6\n" + " SpikeStats 7 50e-6\n" + " Table 8 0.1e-3\n" + " TimeTable 8 0.1e-3\n" + + " Dsolve 10 0.01\n" + " Adaptor 11 0.1\n" + " Func 12 0.1\n" + " Function 12 0.1\n" + " Arith 12 0.1\n" + " BufPool 13 0.1\n" + " Pool 13 0.1\n" + " PoolBase 13 0.1\n" + " CplxEnzBase 14 0.1\n" + " Enz 14 0.1\n" + " EnzBase 14 0.1\n" + " MMenz 14 0.1\n" + " Reac 14 0.1\n" + " ReacBase 14 0.1\n" + " Gsolve (init) 15 0.1\n" + " Ksolve (init) 15 0.1\n" + " Gsolve 16 0.1\n" + " Ksolve 16 0.1\n" + " Stats 17 0.1\n" + " Table2 18 1\n" + " Streamer 19 10\n" + + " HDF5DataWriter 30 1\n" + " HDF5WriterBase 30 1\n" + " NSDFWriter 30 1\n" + " PyRun 30 1\n" + " PostMaster 31 0.01\n" + " \n" + " Note that the other classes are not scheduled at all.", }; static Dinfo< Clock > dinfo; @@ -662,7 +662,7 @@ void Clock::innerReportClock() const cout << "Dts= "; for ( unsigned int i = 0; i < ticks_.size(); ++i ) { - cout << "tick[" << i << "] = " << ticks_[i] << " " << + cout << "tick[" << i << "] = " << ticks_[i] << " " << ticks_[i] * dt_ << endl; } cout << endl; @@ -834,24 +834,24 @@ void Clock::handleReinit( const Eref& e ) * Useful function, only I don't need it yet. Was implemented for Dsolve double Dsolve::findDt( const Eref& e ) { - // Here is the horrible stuff to traverse the message to get the dt. - const Finfo* f = Dsolve::initCinfo()->findFinfo( "reinit" ); - const DestFinfo* df = dynamic_cast< const DestFinfo* >( f ); - assert( df ); - unsigned int fid = df->getFid(); - ObjId caller = e.element()->findCaller( fid ); - const Msg* m = Msg::getMsg( caller ); - assert( m ); - vector< string > src = m->getSrcFieldsOnE1(); - assert( src.size() > 0 ); - string temp = src[0].substr( src[0].length() - 1 ); // reinitxx - unsigned int tick = atoi( temp.c_str() ); - assert( tick < 10 ); - Id clock( 1 ); - assert( clock.element() == m->e1() ); - double dt = LookupField< unsigned int, double >:: - get( clock, "tickDt", tick ); - return dt; + // Here is the horrible stuff to traverse the message to get the dt. + const Finfo* f = Dsolve::initCinfo()->findFinfo( "reinit" ); + const DestFinfo* df = dynamic_cast< const DestFinfo* >( f ); + assert( df ); + unsigned int fid = df->getFid(); + ObjId caller = e.element()->findCaller( fid ); + const Msg* m = Msg::getMsg( caller ); + assert( m ); + vector< string > src = m->getSrcFieldsOnE1(); + assert( src.size() > 0 ); + string temp = src[0].substr( src[0].length() - 1 ); // reinitxx + unsigned int tick = atoi( temp.c_str() ); + assert( tick < 10 ); + Id clock( 1 ); + assert( clock.element() == m->e1() ); + double dt = LookupField< unsigned int, double >:: + get( clock, "tickDt", tick ); + return dt; } */ @@ -1027,7 +1027,7 @@ void Clock::buildDefaultTick() defaultDt_[19] = 10; // For Streamer // 20-29 are not assigned. - defaultDt_[30] = 1; // For the HDF writer + defaultDt_[30] = 1; // For the HDF writer defaultDt_[31] = 0.01; // For the postmaster. } diff --git a/moose-core/shell/Shell.cpp b/moose-core/shell/Shell.cpp index e29b318ace7b31b0c439a6c1f18cdf0c1cea282d..775092c634f768c95caa2021c11a878338491720 100644 --- a/moose-core/shell/Shell.cpp +++ b/moose-core/shell/Shell.cpp @@ -341,7 +341,7 @@ void Shell::doStart( double runtime, bool notify ) *-----------------------------------------------------------------------------*/ vector< ObjId > streamers; wildcardFind( "/##[TYPE=Streamer]", streamers ); - LOG( moose::debug, "total streamers " << streamers.size( ) ); + // LOG( moose::debug, "total streamers " << streamers.size( ) ); for( vector<ObjId>::const_iterator itr = streamers.begin() ; itr != streamers.end(); itr++ ) { diff --git a/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.cpp b/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.cpp index 835dc72b7d31f24c95d585567dee6439a33eb3c2..7f78996d341b5d9a800efb90e23b0f0443deed0c 100644 --- a/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.cpp +++ b/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.cpp @@ -7,22 +7,22 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include <queue> -#include "header.h" +#include "../basecode/header.h" #include "Synapse.h" #include "SynEvent.h" // only using the SynEvent class from this #include "SynHandlerBase.h" -#include "../randnum/Normal.h" // generate normal randum numbers for noisy weight update #include "GraupnerBrunel2012CaPlasticitySynHandler.h" +#include <queue> + const Cinfo* GraupnerBrunel2012CaPlasticitySynHandler::initCinfo() { - static string doc[] = - { - "Name", "GraupnerBrunel2012CaPlasticitySynHandler", - "Author", "Aditya Gilra", - "Description", - "The GraupnerBrunel2012CaPlasticitySynHandler handles synapses" + static string doc[] = + { + "Name", "GraupnerBrunel2012CaPlasticitySynHandler", + "Author", "Aditya Gilra", + "Description", + "The GraupnerBrunel2012CaPlasticitySynHandler handles synapses" "with Ca-based plasticity as per Higgins et al. 2014 and Graupner and Brunel 2012." "Note 1:" " Here, Ca ('chemical Ca') is updated only at each pre-spike, pre-spike+delayD and post-spike!" @@ -43,8 +43,8 @@ const Cinfo* GraupnerBrunel2012CaPlasticitySynHandler::initCinfo() " in its own electrical compartment (=spine)," " only then can you have an 'electrical Ca'" " corresponding to the 'chemical Ca'." - "Three priority queues are used to manage pre, post, and pre+delayD spikes." - }; + "Three priority queues are used to manage pre, post, and pre+delayD spikes." + }; static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > Ca( "Ca", @@ -54,81 +54,81 @@ const Cinfo* GraupnerBrunel2012CaPlasticitySynHandler::initCinfo() "when a pre- or post- spike has occured, or at time delayD after a pre-spike." "Do not use it to control a Ca dependent current, etc." "See notes in the class Description: all pre-synapses get updated via the same post-synaptic Ca.", - &GraupnerBrunel2012CaPlasticitySynHandler::setCa, - &GraupnerBrunel2012CaPlasticitySynHandler::getCa + &GraupnerBrunel2012CaPlasticitySynHandler::setCa, + &GraupnerBrunel2012CaPlasticitySynHandler::getCa ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > CaInit( "CaInit", "CaInit is the initial value for Ca", - &GraupnerBrunel2012CaPlasticitySynHandler::setCaInit, - &GraupnerBrunel2012CaPlasticitySynHandler::getCaInit + &GraupnerBrunel2012CaPlasticitySynHandler::setCaInit, + &GraupnerBrunel2012CaPlasticitySynHandler::getCaInit ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > tauCa( "tauCa", "tauCa is the time constant for decay of Ca", - &GraupnerBrunel2012CaPlasticitySynHandler::setTauCa, - &GraupnerBrunel2012CaPlasticitySynHandler::getTauCa + &GraupnerBrunel2012CaPlasticitySynHandler::setTauCa, + &GraupnerBrunel2012CaPlasticitySynHandler::getTauCa ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > tauSyn( "tauSyn", "tauSyn is the time constant for synaptic weight evolution equation", - &GraupnerBrunel2012CaPlasticitySynHandler::setTauSyn, - &GraupnerBrunel2012CaPlasticitySynHandler::getTauSyn + &GraupnerBrunel2012CaPlasticitySynHandler::setTauSyn, + &GraupnerBrunel2012CaPlasticitySynHandler::getTauSyn ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > CaPre( "CaPre", "CaPre is added to Ca on every pre-spike", - &GraupnerBrunel2012CaPlasticitySynHandler::setCaPre, - &GraupnerBrunel2012CaPlasticitySynHandler::getCaPre + &GraupnerBrunel2012CaPlasticitySynHandler::setCaPre, + &GraupnerBrunel2012CaPlasticitySynHandler::getCaPre ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > CaPost( "CaPost", "CaPost is added to Ca on every post-spike", - &GraupnerBrunel2012CaPlasticitySynHandler::setCaPost, - &GraupnerBrunel2012CaPlasticitySynHandler::getCaPost + &GraupnerBrunel2012CaPlasticitySynHandler::setCaPost, + &GraupnerBrunel2012CaPlasticitySynHandler::getCaPost ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > delayD( "delayD", "Time delay D after pre-spike, when Ca is increased by Capre." " delayD represents NMDA rise time.", - &GraupnerBrunel2012CaPlasticitySynHandler::setDelayD, - &GraupnerBrunel2012CaPlasticitySynHandler::getDelayD + &GraupnerBrunel2012CaPlasticitySynHandler::setDelayD, + &GraupnerBrunel2012CaPlasticitySynHandler::getDelayD ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > gammaP( "gammaP", "gammaP is the potentiation factor for synaptic weight increase if Ca>thetaP", - &GraupnerBrunel2012CaPlasticitySynHandler::setGammaP, - &GraupnerBrunel2012CaPlasticitySynHandler::getGammaP + &GraupnerBrunel2012CaPlasticitySynHandler::setGammaP, + &GraupnerBrunel2012CaPlasticitySynHandler::getGammaP ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > gammaD( "gammaD", "gammaD is the depression factor for synaptic weight decrease if Ca>thetaD", - &GraupnerBrunel2012CaPlasticitySynHandler::setGammaD, - &GraupnerBrunel2012CaPlasticitySynHandler::getGammaD + &GraupnerBrunel2012CaPlasticitySynHandler::setGammaD, + &GraupnerBrunel2012CaPlasticitySynHandler::getGammaD ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > thetaP( "thetaP", "Potentiation threshold for Ca" "User must ensure thetaP>thetaD, else simulation results will be wrong.", - &GraupnerBrunel2012CaPlasticitySynHandler::setThetaP, - &GraupnerBrunel2012CaPlasticitySynHandler::getThetaP + &GraupnerBrunel2012CaPlasticitySynHandler::setThetaP, + &GraupnerBrunel2012CaPlasticitySynHandler::getThetaP ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > thetaD( "thetaD", "Depression threshold for Ca" "User must ensure thetaP>thetaD, else simulation results will be wrong.", - &GraupnerBrunel2012CaPlasticitySynHandler::setThetaD, - &GraupnerBrunel2012CaPlasticitySynHandler::getThetaD + &GraupnerBrunel2012CaPlasticitySynHandler::setThetaD, + &GraupnerBrunel2012CaPlasticitySynHandler::getThetaD ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, bool > bistable( @@ -136,36 +136,36 @@ const Cinfo* GraupnerBrunel2012CaPlasticitySynHandler::initCinfo() "If true, the synapse is bistable as in GraupnerBrunel2012 paper." "The effect of potential on the weight update is usually ignorable" " if Ca is above thetaP and thetaD most of the time.", - &GraupnerBrunel2012CaPlasticitySynHandler::setBistable, - &GraupnerBrunel2012CaPlasticitySynHandler::getBistable + &GraupnerBrunel2012CaPlasticitySynHandler::setBistable, + &GraupnerBrunel2012CaPlasticitySynHandler::getBistable ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, bool > noisy( "noisy", "If true, turn noise on as per noiseSD", - &GraupnerBrunel2012CaPlasticitySynHandler::setNoisy, - &GraupnerBrunel2012CaPlasticitySynHandler::getNoisy + &GraupnerBrunel2012CaPlasticitySynHandler::setNoisy, + &GraupnerBrunel2012CaPlasticitySynHandler::getNoisy ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > noiseSD( "noiseSD", "Standard deviation of noise added to Ca", - &GraupnerBrunel2012CaPlasticitySynHandler::setNoiseSD, - &GraupnerBrunel2012CaPlasticitySynHandler::getNoiseSD + &GraupnerBrunel2012CaPlasticitySynHandler::setNoiseSD, + &GraupnerBrunel2012CaPlasticitySynHandler::getNoiseSD ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > weightMax( "weightMax", "An upper bound on the weight", - &GraupnerBrunel2012CaPlasticitySynHandler::setWeightMax, - &GraupnerBrunel2012CaPlasticitySynHandler::getWeightMax + &GraupnerBrunel2012CaPlasticitySynHandler::setWeightMax, + &GraupnerBrunel2012CaPlasticitySynHandler::getWeightMax ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > weightMin( "weightMin", "A lower bound on the weight", - &GraupnerBrunel2012CaPlasticitySynHandler::setWeightMin, - &GraupnerBrunel2012CaPlasticitySynHandler::getWeightMin + &GraupnerBrunel2012CaPlasticitySynHandler::setWeightMin, + &GraupnerBrunel2012CaPlasticitySynHandler::getWeightMin ); static ValueFinfo< GraupnerBrunel2012CaPlasticitySynHandler, double > weightScale( @@ -173,237 +173,281 @@ const Cinfo* GraupnerBrunel2012CaPlasticitySynHandler::initCinfo() "Scale all pre-synaptic weights by weightScale before adding to activation (default 1.0)" "In the terminology of the paper Higgins et al 2012, weight is synaptic efficacy," "while weightScale*weight is what finally is added to activation variable.", - &GraupnerBrunel2012CaPlasticitySynHandler::setWeightScale, - &GraupnerBrunel2012CaPlasticitySynHandler::getWeightScale + &GraupnerBrunel2012CaPlasticitySynHandler::setWeightScale, + &GraupnerBrunel2012CaPlasticitySynHandler::getWeightScale ); - static DestFinfo addPostSpike( "addPostSpike", + static DestFinfo addPostSpike( + "addPostSpike", "Handles arriving spike messages from post-synaptic neuron, inserts into postEvent queue.", new EpFunc1< GraupnerBrunel2012CaPlasticitySynHandler, \ - double >( &GraupnerBrunel2012CaPlasticitySynHandler::addPostSpike ) ); - - static FieldElementFinfo< SynHandlerBase, Synapse > synFinfo( - "synapse", - "Sets up field Elements for synapse", - Synapse::initCinfo(), - &SynHandlerBase::getSynapse, - &SynHandlerBase::setNumSynapses, - &SynHandlerBase::getNumSynapses - ); - - static Finfo* GraupnerBrunel2012CaPlasticitySynHandlerFinfos[] = { - &synFinfo, // FieldElement - &addPostSpike, // DestFinfo - &Ca, // Field - &CaInit, // Field - &tauCa, // Field - &tauSyn, // Field - &CaPre, // Field - &CaPost, // Field - &delayD, // Field - &thetaP, // Field - &thetaD, // Field - &gammaP, // Field - &gammaD, // Field - &weightMax, // Field - &weightMin, // Field - &weightScale, // Field - &noisy, // Field - &noiseSD, // Field - &bistable // Field - }; - - static Dinfo< GraupnerBrunel2012CaPlasticitySynHandler > dinfo; - static Cinfo synHandlerCinfo ( - "GraupnerBrunel2012CaPlasticitySynHandler", - SynHandlerBase::initCinfo(), - GraupnerBrunel2012CaPlasticitySynHandlerFinfos, - sizeof( GraupnerBrunel2012CaPlasticitySynHandlerFinfos ) / sizeof ( Finfo* ), - &dinfo, - doc, - sizeof( doc ) / sizeof( string ) - ); - - return &synHandlerCinfo; + double >( &GraupnerBrunel2012CaPlasticitySynHandler::addPostSpike ) ); + + static FieldElementFinfo< SynHandlerBase, Synapse > synFinfo( + "synapse", + "Sets up field Elements for synapse", + Synapse::initCinfo(), + &SynHandlerBase::getSynapse, + &SynHandlerBase::setNumSynapses, + &SynHandlerBase::getNumSynapses + ); + + static Finfo* GraupnerBrunel2012CaPlasticitySynHandlerFinfos[] = + { + &synFinfo, // FieldElement + &addPostSpike, // DestFinfo + &Ca, // Field + &CaInit, // Field + &tauCa, // Field + &tauSyn, // Field + &CaPre, // Field + &CaPost, // Field + &delayD, // Field + &thetaP, // Field + &thetaD, // Field + &gammaP, // Field + &gammaD, // Field + &weightMax, // Field + &weightMin, // Field + &weightScale, // Field + &noisy, // Field + &noiseSD, // Field + &bistable // Field + }; + + static Dinfo< GraupnerBrunel2012CaPlasticitySynHandler > dinfo; + static Cinfo synHandlerCinfo ( + "GraupnerBrunel2012CaPlasticitySynHandler", + SynHandlerBase::initCinfo(), + GraupnerBrunel2012CaPlasticitySynHandlerFinfos, + sizeof( GraupnerBrunel2012CaPlasticitySynHandlerFinfos ) / sizeof ( Finfo* ), + &dinfo, + doc, + sizeof( doc ) / sizeof( string ) + ); + + return &synHandlerCinfo; } static const Cinfo* GraupnerBrunel2012CaPlasticitySynHandlerCinfo =\ - GraupnerBrunel2012CaPlasticitySynHandler::initCinfo(); + GraupnerBrunel2012CaPlasticitySynHandler::initCinfo(); GraupnerBrunel2012CaPlasticitySynHandler::GraupnerBrunel2012CaPlasticitySynHandler() { - Ca_ = 0.0; - CaInit_ = 0.0; - tauCa_ = 1.0; - tauSyn_ = 1.0; - CaPre_ = 0.0; - CaPost_ = 0.0; - thetaD_ = 0.0; - thetaP_ = 0.0; - gammaD_ = 0.0; - gammaP_ = 0.0; - delayD_ = 0.0; - weightMin_ = 0.0; - weightMax_ = 0.0; + Ca_ = 0.0; + CaInit_ = 0.0; + tauCa_ = 1.0; + tauSyn_ = 1.0; + CaPre_ = 0.0; + CaPost_ = 0.0; + thetaD_ = 0.0; + thetaP_ = 0.0; + gammaD_ = 0.0; + gammaP_ = 0.0; + delayD_ = 0.0; + weightMin_ = 0.0; + weightMax_ = 0.0; weightScale_ = 1.0; - noisy_ = false; - noiseSD_ = 0.0; - bistable_ = true; - normalGenerator_.setMethod(BOX_MUELLER); // the default ALIAS method is 1000x slower! + noisy_ = false; + noiseSD_ = 0.0; + bistable_ = true; + seed_ = 0; + dist_ = moose::MOOSE_NORMAL_DISTRIBUTION<double>{0, 1}; + reinitSeed(); + + // std::cout << " Mean " << dist_.mean() << " std " << dist_.stddev() << std::endl; } GraupnerBrunel2012CaPlasticitySynHandler::~GraupnerBrunel2012CaPlasticitySynHandler() -{ ; } +{ +} + +void GraupnerBrunel2012CaPlasticitySynHandler::reinitSeed( void ) +{ + if( 0 == seed_ ) + seed_ = moose::getGlobalSeed(); + + if( 0 == seed_ ) + seed_ = rd_(); + + MOOSE_DEBUG( "Seed is set to " << seed_ ); + rng_.seed( seed_ ); +} -GraupnerBrunel2012CaPlasticitySynHandler& GraupnerBrunel2012CaPlasticitySynHandler::operator=\ - ( const GraupnerBrunel2012CaPlasticitySynHandler& ssh) +GraupnerBrunel2012CaPlasticitySynHandler& + GraupnerBrunel2012CaPlasticitySynHandler::operator=( + const GraupnerBrunel2012CaPlasticitySynHandler& ssh + ) { - synapses_ = ssh.synapses_; - for ( vector< Synapse >::iterator - i = synapses_.begin(); i != synapses_.end(); ++i ) - i->setHandler( this ); + synapses_ = ssh.synapses_; + for ( vector< Synapse >::iterator + i = synapses_.begin(); i != synapses_.end(); ++i ) + i->setHandler( this ); - // For no apparent reason, priority queues don't have a clear operation. - while( !events_.empty() ) - events_.pop(); - while( !delayDPreEvents_.empty() ) - events_.pop(); - while( !postEvents_.empty() ) - postEvents_.pop(); + // For no apparent reason, priority queues don't have a clear operation. + while( !events_.empty() ) + events_.pop(); + while( !delayDPreEvents_.empty() ) + events_.pop(); + while( !postEvents_.empty() ) + postEvents_.pop(); - return *this; + return *this; } void GraupnerBrunel2012CaPlasticitySynHandler::vSetNumSynapses( const unsigned int v ) { - unsigned int prevSize = synapses_.size(); - synapses_.resize( v ); - for ( unsigned int i = prevSize; i < v; ++i ) - synapses_[i].setHandler( this ); + unsigned int prevSize = synapses_.size(); + synapses_.resize( v ); + for ( unsigned int i = prevSize; i < v; ++i ) + synapses_[i].setHandler( this ); } unsigned int GraupnerBrunel2012CaPlasticitySynHandler::vGetNumSynapses() const { - return synapses_.size(); + return synapses_.size(); } Synapse* GraupnerBrunel2012CaPlasticitySynHandler::vGetSynapse( unsigned int i ) { - static Synapse dummy; - if ( i < synapses_.size() ) - return &synapses_[i]; - cout << "Warning: GraupnerBrunel2012CaPlasticitySynHandler::getSynapse: index: " << i << - " is out of range: " << synapses_.size() << endl; - return &dummy; + static Synapse dummy; + if ( i < synapses_.size() ) + return &synapses_[i]; + cout << "Warning: GraupnerBrunel2012CaPlasticitySynHandler::getSynapse: index: " << i << + " is out of range: " << synapses_.size() << endl; + return &dummy; } void GraupnerBrunel2012CaPlasticitySynHandler::addSpike( - unsigned int index, double time, double weight ) + unsigned int index, double time, double weight ) { - assert( index < synapses_.size() ); - events_.push( PreSynEvent( index, time, weight ) ); - delayDPreEvents_.push( PreSynEvent( index, time+delayD_, weight ) ); + assert( index < synapses_.size() ); + events_.push( PreSynEvent( index, time, weight ) ); + delayDPreEvents_.push( PreSynEvent( index, time+delayD_, weight ) ); } -double GraupnerBrunel2012CaPlasticitySynHandler::getTopSpike( - unsigned int index ) const +double GraupnerBrunel2012CaPlasticitySynHandler::getTopSpike( + unsigned int index ) const { - if ( events_.empty() ) - return 0.0; - return events_.top().time; + if ( events_.empty() ) + return 0.0; + return events_.top().time; } void GraupnerBrunel2012CaPlasticitySynHandler::addPostSpike( const Eref& e, double time ) { - postEvents_.push( PostSynEvent( time ) ); + postEvents_.push( PostSynEvent( time ) ); } weightFactors GraupnerBrunel2012CaPlasticitySynHandler::updateCaWeightFactors( double currTime ) { - double CaOld = Ca_; - double deltaT = currTime-lastCaUpdateTime_; - // Update Ca, but CaPre and CaPost are added in vProcess() - Ca_ *= exp(-deltaT/tauCa_); - lastCaUpdateTime_ = currTime; - weightFactors wUp; // by default all are set to 0.0 - - // calculate/approximate time spent above potentiation and depression thresholds - // see pg 13 of Higgins et al | October 2014 | Volume 10 | Issue 10 | e1003834 | PLOS Comp Biol - // starting from bottom condition, going upwards in the algorithm given in above paper - if (CaOld <= thetaD_) { - } else if (CaOld <= thetaP_) { - //cout << "tD<Caold<tP" << "\n"; - if (Ca_ <= thetaD_) { - wUp.tD = tauCa_*log(CaOld/thetaD_); - //cout << "Ca<tD" << "\n"; - } else { - wUp.tD = deltaT; - //cout << "Ca>tD" << "\n"; - } - } else { - //cout << "Caold>tP" << "\n"; - if (Ca_ <= thetaD_) { - wUp.tP = tauCa_*log(CaOld/thetaP_); - wUp.tD = tauCa_*log(thetaP_/thetaD_); - //cout << "Ca<tD" << "\n"; - //cout << "Caold = " << CaOld << "thetaP = " << thetaP_ << "\n"; - } else if (Ca_ <= thetaP_) { - wUp.tP = tauCa_*log(CaOld/thetaP_); - wUp.tD = deltaT - wUp.tP; - //cout << "Ca<tP" << "\n"; - } else { - wUp.tP = deltaT; - //cout << "Ca>tP" << "\n"; - } + double CaOld = Ca_; + double deltaT = currTime-lastCaUpdateTime_; + // Update Ca, but CaPre and CaPost are added in vProcess() + Ca_ *= exp(-deltaT/tauCa_); + lastCaUpdateTime_ = currTime; + weightFactors wUp; // by default all are set to 0.0 + + // calculate/approximate time spent above potentiation and depression thresholds + // see pg 13 of Higgins et al | October 2014 | Volume 10 | Issue 10 | e1003834 | PLOS Comp Biol + // starting from bottom condition, going upwards in the algorithm given in above paper + if (CaOld <= thetaD_) + { + } + else if (CaOld <= thetaP_) + { + //cout << "tD<Caold<tP" << "\n"; + if (Ca_ <= thetaD_) + { + wUp.tD = tauCa_*log(CaOld/thetaD_); + //cout << "Ca<tD" << "\n"; + } + else + { + wUp.tD = deltaT; + //cout << "Ca>tD" << "\n"; + } + } + else + { + //cout << "Caold>tP" << "\n"; + if (Ca_ <= thetaD_) + { + wUp.tP = tauCa_*log(CaOld/thetaP_); + wUp.tD = tauCa_*log(thetaP_/thetaD_); + //cout << "Ca<tD" << "\n"; + //cout << "Caold = " << CaOld << "thetaP = " << thetaP_ << "\n"; + } + else if (Ca_ <= thetaP_) + { + wUp.tP = tauCa_*log(CaOld/thetaP_); + wUp.tD = deltaT - wUp.tP; + //cout << "Ca<tP" << "\n"; + } + else + { + wUp.tP = deltaT; + //cout << "Ca>tP" << "\n"; + } + } + wUp.t0 = deltaT - wUp.tP - wUp.tD; + + // Depending on tP and tD, I return A,B,C factors for weight update + // (see page 13 of Higgins et al 2014). + // A,B,C,D,E are used to compute the weight change for one or multiple synapses + // A is weight independent, B,D are weight dependent and C,E are accumulated noise + if (wUp.tP > 0) + { + double gPgD = gammaP_+gammaD_; + wUp.A = gammaP_/gPgD*(1.0-exp(-wUp.tP*gPgD/tauSyn_)); + wUp.B = exp(-wUp.tP*gPgD/tauSyn_); + if (noisy_) + { + wUp.C = noiseSD_ * dist_(rng_) * + sqrt( ( 1.0-exp(-2*gPgD*wUp.tP/tauSyn_) ) / gPgD ); + // cout << " A = " << wUp.A << " B = " << wUp.B << " C = " << wUp.C << "\n"; } - wUp.t0 = deltaT - wUp.tP - wUp.tD; - - // Depending on tP and tD, I return A,B,C factors for weight update - // (see page 13 of Higgins et al 2014). - // A,B,C,D,E are used to compute the weight change for one or multiple synapses - // A is weight independent, B,D are weight dependent and C,E are accumulated noise - if (wUp.tP > 0) { - double gPgD = gammaP_+gammaD_; - wUp.A = gammaP_/gPgD*(1.0-exp(-wUp.tP*gPgD/tauSyn_)); - wUp.B = exp(-wUp.tP*gPgD/tauSyn_); - if (noisy_) { - wUp.C = noiseSD_ * normalGenerator_.getNextSample() * - sqrt( ( 1.0-exp(-2*gPgD*wUp.tP/tauSyn_) ) / gPgD ); - //cout << "A = " << wUp.A << " B = " << wUp.B << " C = " << wUp.C << "\n"; - } else { - wUp.C = 0.0; - } + else + { + wUp.C = 0.0; } + } - if (wUp.tD > 0) { - wUp.D = exp(-wUp.tD*gammaD_/tauSyn_); - if (noisy_) { - wUp.E = noiseSD_ * normalGenerator_.getNextSample() * - sqrt( ( 1.0-exp(-2*gammaD_*wUp.tD/tauSyn_) ) / 2.0/gammaD_ ); - //cout << "D = " << wUp.D << " E = " << wUp.E << "\n"; - } else{ - wUp.E = 0.0; - } + if (wUp.tD > 0) + { + wUp.D = exp(-wUp.tD*gammaD_/tauSyn_); + if (noisy_) + { + wUp.E = noiseSD_ * dist_( rng_ ) * + sqrt( ( 1.0-exp(-2*gammaD_*wUp.tD/tauSyn_) ) / 2.0/gammaD_ ); + //cout << "D = " << wUp.D << " E = " << wUp.E << "\n"; + } + else + { + wUp.E = 0.0; } + } - //cout << currTime << " tD = " << wUp.tD << " tP = " << wUp.tP << "\n"; - // tP, tD, A, B, C, D, E of wUp - // are set to 0.0 by default in struct constructor - return wUp; // return by value, i.e. copies the struct, so wUp going out of scope doesn't matter - // malloc and returning pointer is more expensive for small structs - // see: http://stackoverflow.com/questions/9590827/is-it-safe-to-return-a-struct-in-c-c + //cout << currTime << " tD = " << wUp.tD << " tP = " << wUp.tP << "\n"; + // tP, tD, A, B, C, D, E of wUp + // are set to 0.0 by default in struct constructor + return wUp; // return by value, i.e. copies the struct, so wUp going out of scope doesn't matter + // malloc and returning pointer is more expensive for small structs + // see: http://stackoverflow.com/questions/9590827/is-it-safe-to-return-a-struct-in-c-c } void GraupnerBrunel2012CaPlasticitySynHandler::updateWeight( Synapse* synPtr, weightFactors *wFacPtr ) { double newWeight = synPtr->getWeight(); //cout << " oldweight = " << newWeight << "\n"; - if (wFacPtr->tP > 0.0) { + if (wFacPtr->tP > 0.0) + { newWeight = wFacPtr->A + wFacPtr->B*newWeight + wFacPtr->C; //cout << " midweight = " << newWeight << "\n"; } - if (wFacPtr->tD > 0.0) { + if (wFacPtr->tD > 0.0) + { newWeight = wFacPtr->D*newWeight + wFacPtr->E; // update the weight again //cout << " newweight = " << newWeight << "\n"; } @@ -411,12 +455,16 @@ void GraupnerBrunel2012CaPlasticitySynHandler::updateWeight( Synapse* synPtr, we // potential is usually ignorable when t0 is small, // i.e. Ca is mostly above thetaD or thetaP //cout << "before bistable newWeight = " << newWeight << "\n"; - if (bistable_) { + if (bistable_) + { double chi0 = pow((newWeight-0.5),2.0) / (newWeight*(newWeight-1)); double weightDeviation = 0.5*sqrt( 1.0 + 1.0/(chi0*exp(wFacPtr->t0/2.0/tauSyn_)-1.0) ); - if (newWeight<0.5) { + if (newWeight<0.5) + { newWeight = 0.5 - weightDeviation; - } else { + } + else + { newWeight = 0.5 + weightDeviation; } } @@ -432,18 +480,19 @@ void GraupnerBrunel2012CaPlasticitySynHandler::updateWeight( Synapse* synPtr, we void GraupnerBrunel2012CaPlasticitySynHandler::vProcess( const Eref& e, ProcPtr p ) { - double activation = 0.0; + double activation = 0.0; double currTime = p->currTime; bool CaFactorsUpdated = false; // Ca-decay and weight Factors updation is done only once - // if any pre-spike, pre-spike+delayD or post-spike occurs - // Ca is bumped by CaPre and CaPost on - // pre-spike+delayD and post-spike respectively - // At the end, if any event above occurred, - // change all pre-synaptic weights based on Ca + // if any pre-spike, pre-spike+delayD or post-spike occurs + // Ca is bumped by CaPre and CaPost on + // pre-spike+delayD and post-spike respectively + // At the end, if any event above occurred, + // change all pre-synaptic weights based on Ca weightFactors wFacs; // process pre-synaptic spike events for activation, Ca and weight update - while( !events_.empty() && events_.top().time <= currTime ) { + while( !events_.empty() && events_.top().time <= currTime ) + { PreSynEvent currEvent = events_.top(); unsigned int synIndex = currEvent.synIndex; @@ -472,56 +521,63 @@ void GraupnerBrunel2012CaPlasticitySynHandler::vProcess( const Eref& e, ProcPtr // need to send it divided by dt. // Can connect activation to SynChan (double exp) // or to LIF as an impulse to voltage. - //activation += currEvent.weight * weightScale_ / p->dt; + //activation += currEvent.weight * weightScale_ / p->dt; activation += currSynPtr->getWeight() * weightScale_ / p->dt; // update only once for this time-step if an event occurs - if (!CaFactorsUpdated) { + if (!CaFactorsUpdated) + { // update Ca and weightFactors wFacs = updateCaWeightFactors( currTime ); CaFactorsUpdated = true; } - events_.pop(); - } - if ( activation != 0.0 ) - SynHandlerBase::activationOut()->send( e, activation ); + events_.pop(); + } + if ( activation != 0.0 ) + SynHandlerBase::activationOut()->send( e, activation ); // process delayed pre-synaptic spike events for Ca and weight update // delayD after pre-spike accounts for NMDA rise time - while( !delayDPreEvents_.empty() && delayDPreEvents_.top().time <= currTime ) { + while( !delayDPreEvents_.empty() && delayDPreEvents_.top().time <= currTime ) + { // Update Ca, and add CaPre // update only once for this time-step if an event occurs - if (!CaFactorsUpdated) { + if (!CaFactorsUpdated) + { // update Ca and weightFactors wFacs = updateCaWeightFactors( currTime ); CaFactorsUpdated = true; } Ca_ += CaPre_; - delayDPreEvents_.pop(); - } + delayDPreEvents_.pop(); + } // process post-synaptic spike events for Ca and weight update - while( !postEvents_.empty() && postEvents_.top().time <= currTime ) { + while( !postEvents_.empty() && postEvents_.top().time <= currTime ) + { // update Ca, then add CaPost // update only once for this time-step if an event occurs - if (!CaFactorsUpdated) { + if (!CaFactorsUpdated) + { // update Ca and weightFactors wFacs = updateCaWeightFactors( currTime ); CaFactorsUpdated = true; } Ca_ += CaPost_; - postEvents_.pop(); - } + postEvents_.pop(); + } // If any event has happened, update all pre-synaptic weights // If you want individual Ca for each pre-synapse // create individual SynHandlers for each - if (CaFactorsUpdated) { + if (CaFactorsUpdated) + { // Change weight of all synapses - for (unsigned int i=0; i<synapses_.size(); i++) { + for (unsigned int i=0; i<synapses_.size(); i++) + { // Warning, coder! 'Synapse currSyn = synapses_[i];' is wrong, // it creates a new, shallow-copied object. // We want only to point to the same object. @@ -534,199 +590,199 @@ void GraupnerBrunel2012CaPlasticitySynHandler::vProcess( const Eref& e, ProcPtr void GraupnerBrunel2012CaPlasticitySynHandler::vReinit( const Eref& e, ProcPtr p ) { - // For no apparent reason, priority queues don't have a clear operation. - while( !events_.empty() ) - events_.pop(); - while( !delayDPreEvents_.empty() ) - events_.pop(); - while( !postEvents_.empty() ) - postEvents_.pop(); + // For no apparent reason, priority queues don't have a clear operation. + while( !events_.empty() ) + events_.pop(); + while( !delayDPreEvents_.empty() ) + events_.pop(); + while( !postEvents_.empty() ) + postEvents_.pop(); Ca_ = CaInit_; } unsigned int GraupnerBrunel2012CaPlasticitySynHandler::addSynapse() { - unsigned int newSynIndex = synapses_.size(); - synapses_.resize( newSynIndex + 1 ); - synapses_[newSynIndex].setHandler( this ); - return newSynIndex; + unsigned int newSynIndex = synapses_.size(); + synapses_.resize( newSynIndex + 1 ); + synapses_[newSynIndex].setHandler( this ); + return newSynIndex; } void GraupnerBrunel2012CaPlasticitySynHandler::dropSynapse( unsigned int msgLookup ) { - assert( msgLookup < synapses_.size() ); - synapses_[msgLookup].setWeight( -1.0 ); + assert( msgLookup < synapses_.size() ); + synapses_[msgLookup].setWeight( -1.0 ); } void GraupnerBrunel2012CaPlasticitySynHandler::setCa( const double v ) { - Ca_ = v; + Ca_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getCa() const { - return Ca_; + return Ca_; } void GraupnerBrunel2012CaPlasticitySynHandler::setCaInit( const double v ) { - CaInit_ = v; + CaInit_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getCaInit() const { - return CaInit_; + return CaInit_; } void GraupnerBrunel2012CaPlasticitySynHandler::setCaPre( const double v ) { - CaPre_ = v; + CaPre_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getCaPre() const { - return CaPre_; + return CaPre_; } void GraupnerBrunel2012CaPlasticitySynHandler::setCaPost( const double v ) { - CaPost_ = v; + CaPost_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getCaPost() const { - return CaPost_; + return CaPost_; } void GraupnerBrunel2012CaPlasticitySynHandler::setThetaP( const double v ) { - thetaP_ = v; + thetaP_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getThetaP() const { - return thetaP_; + return thetaP_; } void GraupnerBrunel2012CaPlasticitySynHandler::setThetaD( const double v ) { - thetaD_ = v; + thetaD_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getThetaD() const { - return thetaD_; + return thetaD_; } void GraupnerBrunel2012CaPlasticitySynHandler::setGammaD( const double v ) { - gammaD_ = v; + gammaD_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getGammaD() const { - return gammaD_; + return gammaD_; } void GraupnerBrunel2012CaPlasticitySynHandler::setGammaP( const double v ) { - gammaP_ = v; + gammaP_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getGammaP() const { - return gammaP_; + return gammaP_; } void GraupnerBrunel2012CaPlasticitySynHandler::setDelayD( const double v ) { - delayD_ = v; + delayD_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getDelayD() const { - return delayD_; + return delayD_; } void GraupnerBrunel2012CaPlasticitySynHandler::setTauCa( const double v ) { - if ( rangeWarning( "tauCa", v ) ) return; - tauCa_ = v; + if ( rangeWarning( "tauCa", v ) ) return; + tauCa_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getTauCa() const { - return tauCa_; + return tauCa_; } void GraupnerBrunel2012CaPlasticitySynHandler::setTauSyn( const double v ) { - if ( rangeWarning( "tauSyn", v ) ) return; - tauSyn_ = v; + if ( rangeWarning( "tauSyn", v ) ) return; + tauSyn_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getTauSyn() const { - return tauSyn_; + return tauSyn_; } void GraupnerBrunel2012CaPlasticitySynHandler::setNoisy( const bool v ) { - noisy_ = v; + noisy_ = v; } bool GraupnerBrunel2012CaPlasticitySynHandler::getNoisy() const { - return noisy_; + return noisy_; } void GraupnerBrunel2012CaPlasticitySynHandler::setNoiseSD( const double v ) { - noiseSD_ = v; + noiseSD_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getNoiseSD() const { - return noiseSD_; + return noiseSD_; } void GraupnerBrunel2012CaPlasticitySynHandler::setBistable( const bool v ) { - bistable_ = v; + bistable_ = v; } bool GraupnerBrunel2012CaPlasticitySynHandler::getBistable() const { - return bistable_; + return bistable_; } void GraupnerBrunel2012CaPlasticitySynHandler::setWeightMax( const double v ) { - weightMax_ = v; + weightMax_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getWeightMax() const { - return weightMax_; + return weightMax_; } void GraupnerBrunel2012CaPlasticitySynHandler::setWeightMin( const double v ) { - weightMin_ = v; + weightMin_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getWeightMin() const { - return weightMin_; + return weightMin_; } void GraupnerBrunel2012CaPlasticitySynHandler::setWeightScale( const double v ) { - weightScale_ = v; + weightScale_ = v; } double GraupnerBrunel2012CaPlasticitySynHandler::getWeightScale() const { - return weightScale_; + return weightScale_; } diff --git a/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.h b/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.h index f7888602545b6b9742369e12dca5a4fcbbbb44be..936d9e101a1575f4211e17794a541cba170c6227 100644 --- a/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.h +++ b/moose-core/synapse/GraupnerBrunel2012CaPlasticitySynHandler.h @@ -10,55 +10,20 @@ #ifndef _GRAUPNER_BRUNEL_2012_CA_PLASTICITY_SYN_HANDLER_H #define _GRAUPNER_BRUNEL_2012_CA_PLASTICITY_SYN_HANDLER_H -/* -class PreSynEvent: public SynEvent -{ - public: - PreSynEvent() - : SynEvent(), // call the parent constructor with default args - // by default calls without args, so no need really - synIndex( 0 ) - {} - - PreSynEvent( unsigned int i, double t, double w ) - : SynEvent(t,w),// call the parent constructor with given args - synIndex( i ) - {;} - - unsigned int synIndex; -}; - -class PostSynEvent -{ - public: - PostSynEvent() - : time( 0.0 ) - {;} - - PostSynEvent( double t ) - : time( t ) - {;} +#include "../basecode/global.h" +#include "../randnum/RNG.h" - double time; -}; +#include <queue> -struct ComparePostSynEvent -{ - bool operator()(const PostSynEvent& lhs, const PostSynEvent& rhs) const - { - // Note that this is backwards. We want the smallest timestamp - // on the top of the events priority_queue. - return lhs.time > rhs.time; - } -}; -*/ +using namespace std; // see pg 13 of Higgins et al | October 2014 | Volume 10 | Issue 10 | e1003834 | PLOS Comp Biol // tP and tD are times spent above potentiation and depression thresholds // Depending on tP and tD, I return A,B,C factors for weight update (see pg 13 ref above) // A,B,C are used to compute the weight change for one or multiple synapses // A is weight independent, B,D are weight dependent and C,E are accumulated noise -struct weightFactors { +struct weightFactors +{ weightFactors() : tP(0.0), tD(0.0), A(0.0), B(0.0), C(0.0), D(0.0), E(0.0) {}; double tP; // time spent above potentiation threshold (thetaP) between two events double tD; // time spent between depression and potentiation thresholds between two events @@ -77,94 +42,106 @@ struct weightFactors { */ class GraupnerBrunel2012CaPlasticitySynHandler: public SynHandlerBase { - public: - GraupnerBrunel2012CaPlasticitySynHandler(); - ~GraupnerBrunel2012CaPlasticitySynHandler(); - GraupnerBrunel2012CaPlasticitySynHandler& operator \ - = ( const GraupnerBrunel2012CaPlasticitySynHandler& other ); - - //////////////////////////////////////////////////////////////// - // Inherited virtual functions from SynHandlerBase - //////////////////////////////////////////////////////////////// - void vSetNumSynapses( unsigned int num ); - unsigned int vGetNumSynapses() const; - Synapse* vGetSynapse( unsigned int i ); - void vProcess( const Eref& e, ProcPtr p ); - void vReinit( const Eref& e, ProcPtr p ); - /// Adds a new synapse, returns its index. - unsigned int addSynapse(); - void dropSynapse( unsigned int droppedSynNumber ); - void addSpike( unsigned int index, double time, double weight ); - double getTopSpike( unsigned int index ) const; - //////////////////////////////////////////////////////////////// - void addPostSpike( const Eref& e, double time ); - - void setCa( double v ); - double getCa() const; - void setCaInit( double v ); - double getCaInit() const; - void setTauCa( double v ); - double getTauCa() const; - void setTauSyn( double v ); - double getTauSyn() const; - void setNoiseSD( double v ); - double getNoiseSD() const; - void setNoisy( bool v ); - bool getNoisy() const; - void setBistable( bool v ); - bool getBistable() const; - - void setCaPre( double v ); - double getCaPre() const; - void setCaPost( double v ); - double getCaPost() const; - void setDelayD( double v ); - double getDelayD() const; - - void setThetaD( double v ); - double getThetaD() const; - void setThetaP( double v ); - double getThetaP() const; - void setGammaD( double v ); - double getGammaD() const; - void setGammaP( double v ); - double getGammaP() const; - - void setWeightMax( double v ); - double getWeightMax() const; - void setWeightMin( double v ); - double getWeightMin() const; - void setWeightScale( double v ); - double getWeightScale() const; - - weightFactors updateCaWeightFactors( double currTime ); - void updateWeight( Synapse* synPtr, weightFactors *wFacPtr ); - - static const Cinfo* initCinfo(); - private: - vector< Synapse > synapses_; - priority_queue< PreSynEvent, vector< PreSynEvent >, CompareSynEvent > events_; - priority_queue< PreSynEvent, vector< PreSynEvent >, CompareSynEvent > delayDPreEvents_; - priority_queue< PostSynEvent, vector< PostSynEvent >, ComparePostSynEvent > postEvents_; - double Ca_; - double CaInit_; - double tauCa_; - double tauSyn_; - double CaPre_; - double CaPost_; - double delayD_; - bool noisy_; - double noiseSD_; - bool bistable_; - double thetaD_; - double thetaP_; - double gammaD_; - double gammaP_; - double weightMax_; - double weightMin_; - double weightScale_; - double lastCaUpdateTime_; - Normal normalGenerator_; +public: + GraupnerBrunel2012CaPlasticitySynHandler(); + ~GraupnerBrunel2012CaPlasticitySynHandler(); + GraupnerBrunel2012CaPlasticitySynHandler& operator=( + const GraupnerBrunel2012CaPlasticitySynHandler& other ); + + //////////////////////////////////////////////////////////////// + // Inherited virtual functions from SynHandlerBase + //////////////////////////////////////////////////////////////// + void vSetNumSynapses( unsigned int num ); + unsigned int vGetNumSynapses() const; + Synapse* vGetSynapse( unsigned int i ); + void vProcess( const Eref& e, ProcPtr p ); + void vReinit( const Eref& e, ProcPtr p ); + /// Adds a new synapse, returns its index. + unsigned int addSynapse(); + void dropSynapse( unsigned int droppedSynNumber ); + void addSpike( unsigned int index, double time, double weight ); + double getTopSpike( unsigned int index ) const; + //////////////////////////////////////////////////////////////// + void addPostSpike( const Eref& e, double time ); + + void setCa( double v ); + double getCa() const; + void setCaInit( double v ); + double getCaInit() const; + void setTauCa( double v ); + double getTauCa() const; + void setTauSyn( double v ); + double getTauSyn() const; + void setNoiseSD( double v ); + double getNoiseSD() const; + void setNoisy( bool v ); + bool getNoisy() const; + void setBistable( bool v ); + bool getBistable() const; + + void setCaPre( double v ); + double getCaPre() const; + void setCaPost( double v ); + double getCaPost() const; + void setDelayD( double v ); + double getDelayD() const; + + void setThetaD( double v ); + double getThetaD() const; + void setThetaP( double v ); + double getThetaP() const; + void setGammaD( double v ); + double getGammaD() const; + void setGammaP( double v ); + double getGammaP() const; + + void setWeightMax( double v ); + double getWeightMax() const; + void setWeightMin( double v ); + double getWeightMin() const; + void setWeightScale( double v ); + double getWeightScale() const; + + weightFactors updateCaWeightFactors( double currTime ); + void updateWeight( Synapse* synPtr, weightFactors *wFacPtr ); + + void reinitSeed( ); + + static const Cinfo* initCinfo(); + +private: + + vector< Synapse > synapses_; + + priority_queue< PreSynEvent, vector< PreSynEvent >, CompareSynEvent > events_; + priority_queue< PreSynEvent, vector< PreSynEvent >, CompareSynEvent > delayDPreEvents_; + priority_queue< PostSynEvent, vector< PostSynEvent >, ComparePostSynEvent > postEvents_; + + double Ca_; + double CaInit_; + double tauCa_; + double tauSyn_; + double CaPre_; + double CaPost_; + double delayD_; + bool noisy_; + double noiseSD_; + bool bistable_; + double thetaD_; + double thetaP_; + double gammaD_; + double gammaP_; + double weightMax_; + double weightMin_; + double weightScale_; + double lastCaUpdateTime_; + + // NormalRng normalGenerator_; + unsigned long seed_; + moose::MOOSE_RANDOM_DEVICE rd_; + moose::MOOSE_NORMAL_DISTRIBUTION<double> dist_; + moose::MOOSE_RNG_DEFAULT_ENGINE rng_; + }; #endif // _GRAUPNER_BRUNEL_2012_CA_PLASTICITY_SYN_HANDLER_H diff --git a/moose-core/synapse/SimpleSynHandler.h b/moose-core/synapse/SimpleSynHandler.h index 22ee6c90e8eb366da221254d9fc6a82dc0c3d0d2..687d8862308f98d3bd1a310219ff1933e941e6d2 100644 --- a/moose-core/synapse/SimpleSynHandler.h +++ b/moose-core/synapse/SimpleSynHandler.h @@ -10,6 +10,8 @@ #ifndef _SIMPLE_SYN_HANDLER_H #define _SIMPLE_SYN_HANDLER_H +#include <queue> + /* class SynEvent { diff --git a/moose-core/synapse/SynHandlerBase.cpp b/moose-core/synapse/SynHandlerBase.cpp index 3c30a30bf1702accb1ce7ad378208a1eb51a0afd..6c3251456f1b369cc2ca191505b586b9d0e3da70 100644 --- a/moose-core/synapse/SynHandlerBase.cpp +++ b/moose-core/synapse/SynHandlerBase.cpp @@ -13,13 +13,14 @@ static const double RANGE = 1.0e-15; -SrcFinfo1< double >* SynHandlerBase::activationOut() { - static SrcFinfo1< double > activationOut( - "activationOut", - "Sends out level of activation on all synapses converging to " - "this SynHandler" - ); - return &activationOut; +SrcFinfo1< double >* SynHandlerBase::activationOut() +{ + static SrcFinfo1< double > activationOut( + "activationOut", + "Sends out level of activation on all synapses converging to " + "this SynHandler" + ); + return &activationOut; } /** @@ -29,60 +30,61 @@ SrcFinfo1< double >* SynHandlerBase::activationOut() { */ const Cinfo* SynHandlerBase::initCinfo() { - static ValueFinfo< SynHandlerBase, unsigned int > numSynapses( - "numSynapses", - "Number of synapses on SynHandler. Duplicate field for num_synapse", - &SynHandlerBase::setNumSynapses, - &SynHandlerBase::getNumSynapses - ); - ////////////////////////////////////////////////////////////////////// - static DestFinfo process( "process", - "Handles 'process' call. Checks if any spike events are due for" - "handling at this timestep, and does learning rule stuff if needed", - new ProcOpFunc< SynHandlerBase >(& SynHandlerBase::process ) ); - static DestFinfo reinit( "reinit", - "Handles 'reinit' call. Initializes all the synapses.", - new ProcOpFunc< SynHandlerBase >(& SynHandlerBase::reinit ) ); - - static Finfo* processShared[] = - { - &process, &reinit - }; - static SharedFinfo proc( "proc", - "Shared Finfo to receive Process messages from the clock.", - processShared, sizeof( processShared ) / sizeof( Finfo* ) - ); - - ////////////////////////////////////////////////////////////////////// - static Finfo* synHandlerFinfos[] = { - &numSynapses, // Value - activationOut(), // SrcFinfo - &proc, // SharedFinfo - }; - - static string doc[] = - { - "Name", "SynHandlerBase", - "Author", "Upi Bhalla", - "Description", - "Base class for handling synapse arrays converging onto a given " - "channel or integrate-and-fire neuron. This class provides the " - "interface for channels/intFires to connect to a range of synapse " - "types, including simple synapses, synapses with different " - "plasticity rules, and variants yet to be implemented. " - }; - static ZeroSizeDinfo< int > dinfo; - static Cinfo synHandlerCinfo ( - "SynHandlerBase", - Neutral::initCinfo(), - synHandlerFinfos, - sizeof( synHandlerFinfos ) / sizeof ( Finfo* ), - &dinfo, - doc, - sizeof( doc ) / sizeof( string ) - ); - - return &synHandlerCinfo; + static ValueFinfo< SynHandlerBase, unsigned int > numSynapses( + "numSynapses", + "Number of synapses on SynHandler. Duplicate field for num_synapse", + &SynHandlerBase::setNumSynapses, + &SynHandlerBase::getNumSynapses + ); + ////////////////////////////////////////////////////////////////////// + static DestFinfo process( "process", + "Handles 'process' call. Checks if any spike events are due for" + "handling at this timestep, and does learning rule stuff if needed", + new ProcOpFunc< SynHandlerBase >(& SynHandlerBase::process ) ); + static DestFinfo reinit( "reinit", + "Handles 'reinit' call. Initializes all the synapses.", + new ProcOpFunc< SynHandlerBase >(& SynHandlerBase::reinit ) ); + + static Finfo* processShared[] = + { + &process, &reinit + }; + static SharedFinfo proc( "proc", + "Shared Finfo to receive Process messages from the clock.", + processShared, sizeof( processShared ) / sizeof( Finfo* ) + ); + + ////////////////////////////////////////////////////////////////////// + static Finfo* synHandlerFinfos[] = + { + &numSynapses, // Value + activationOut(), // SrcFinfo + &proc, // SharedFinfo + }; + + static string doc[] = + { + "Name", "SynHandlerBase", + "Author", "Upi Bhalla", + "Description", + "Base class for handling synapse arrays converging onto a given " + "channel or integrate-and-fire neuron. This class provides the " + "interface for channels/intFires to connect to a range of synapse " + "types, including simple synapses, synapses with different " + "plasticity rules, and variants yet to be implemented. " + }; + static ZeroSizeDinfo< int > dinfo; + static Cinfo synHandlerCinfo ( + "SynHandlerBase", + Neutral::initCinfo(), + synHandlerFinfos, + sizeof( synHandlerFinfos ) / sizeof ( Finfo* ), + &dinfo, + doc, + sizeof( doc ) / sizeof( string ) + ); + + return &synHandlerCinfo; } static const Cinfo* synHandlerCinfo = SynHandlerBase::initCinfo(); @@ -90,44 +92,49 @@ static const Cinfo* synHandlerCinfo = SynHandlerBase::initCinfo(); //////////////////////////////////////////////////////////////////////// SynHandlerBase::SynHandlerBase() -{ ; } +{ + ; +} SynHandlerBase::~SynHandlerBase() -{ ; } +{ + ; +} void SynHandlerBase::setNumSynapses( unsigned int num ) { - vSetNumSynapses( num ); + vSetNumSynapses( num ); } unsigned int SynHandlerBase::getNumSynapses() const { - return vGetNumSynapses(); + return vGetNumSynapses(); } Synapse* SynHandlerBase::getSynapse( unsigned int i ) { - return vGetSynapse( i ); + return vGetSynapse( i ); } void SynHandlerBase::process( const Eref& e, ProcPtr p ) { - vProcess( e, p ); + vProcess( e, p ); } void SynHandlerBase::reinit( const Eref& e, ProcPtr p ) { - vReinit( e, p ); + vReinit( e, p ); } bool SynHandlerBase::rangeWarning( const string& field, double value ) { - if ( value < RANGE ) { - cout << "Warning: Ignored attempt to set " << field << - " of SynHandler " << - // c->target().e->name() << - " to less than " << RANGE << endl; - return 1; - } - return 0; + if ( value < RANGE ) + { + cout << "Warning: Ignored attempt to set " << field << + " of SynHandler " << + // c->target().e->name() << + " to less than " << RANGE << endl; + return 1; + } + return 0; } diff --git a/moose-core/synapse/SynHandlerBase.h b/moose-core/synapse/SynHandlerBase.h index e3b3a3834c9008cff8e217a75c7580aa51d2f4d7..d0d3d43a076d1289b918a6b7887b8778ec6544d9 100644 --- a/moose-core/synapse/SynHandlerBase.h +++ b/moose-core/synapse/SynHandlerBase.h @@ -21,77 +21,79 @@ class Synapse; */ class SynHandlerBase { - public: - SynHandlerBase(); - virtual ~SynHandlerBase(); +public: + SynHandlerBase(); + virtual ~SynHandlerBase(); - //////////////////////////////////////////////////////////////// - // Field assignment stuff. - //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + // Field assignment stuff. + //////////////////////////////////////////////////////////////// - /** - * Resizes the synapse storage - */ - void setNumSynapses( unsigned int num ); + /** + * Resizes the synapse storage + */ + void setNumSynapses( unsigned int num ); - /** - * Returns number of synapses defined. - */ - unsigned int getNumSynapses() const; + /** + * Returns number of synapses defined. + */ + unsigned int getNumSynapses() const; - /** - * Gets specified synapse - */ - Synapse* getSynapse( unsigned int i ); - //////////////////////////////////////////////////////////////// + /** + * Gets specified synapse + */ + Synapse* getSynapse( unsigned int i ); + //////////////////////////////////////////////////////////////// - void process( const Eref& e, ProcPtr p ); - void reinit( const Eref& e, ProcPtr p ); + void process( const Eref& e, ProcPtr p ); + void reinit( const Eref& e, ProcPtr p ); - /** - * A utility function to check for assignment to fields that - * must be > 0 - */ - bool rangeWarning( const string& field, double value ); + /** + * A utility function to check for assignment to fields that + * must be > 0 + */ + bool rangeWarning( const string& field, double value ); - //////////////////////////////////////////////////////////////// - /** - * Adds a new synapse, returns its index. This is - * triggered by addMsg of inputs to the child synapse. The - * SynHandler has to ensure that we have enough synapses allocated - * to handle the new message, and the return value is used so that - * the new message knows the fieldIndex to send the message to. - */ - virtual unsigned int addSynapse() = 0; + //////////////////////////////////////////////////////////////// + /** + * Adds a new synapse, returns its index. This is + * triggered by addMsg of inputs to the child synapse. The + * SynHandler has to ensure that we have enough synapses allocated + * to handle the new message, and the return value is used so that + * the new message knows the fieldIndex to send the message to. + */ + virtual unsigned int addSynapse() = 0; - /** - * Drops an existing synapse, triggered by deleteMsg of an input - * to the child synapse. This is a little messy because we can't - * change the indices of the other synapses. The Handler has to - * figure out how to handle the 'holes' in its array of synapses. - */ - virtual void dropSynapse( unsigned int droppedSynNumber ) = 0; + /** + * Drops an existing synapse, triggered by deleteMsg of an input + * to the child synapse. This is a little messy because we can't + * change the indices of the other synapses. The Handler has to + * figure out how to handle the 'holes' in its array of synapses. + */ + virtual void dropSynapse( unsigned int droppedSynNumber ) = 0; + + /** + * Record arrival of a new spike event. The 'time' is time for + * eventual arrival of the spike, and is typically well in the + * future. The index specifies which synapse the spike came to. + */ + virtual void addSpike( + unsigned int index, double time, double weight ) = 0; + virtual double getTopSpike( unsigned int index ) const = 0; + //////////////////////////////////////////////////////////////// + // Virtual func definitions for fields. + //////////////////////////////////////////////////////////////// + virtual void vSetNumSynapses( unsigned int num ) = 0; + virtual unsigned int vGetNumSynapses() const = 0; + virtual Synapse* vGetSynapse( unsigned int i ) = 0; + virtual void vProcess( const Eref& e, ProcPtr p ) = 0; + virtual void vReinit( const Eref& e, ProcPtr p ) = 0; + //////////////////////////////////////////////////////////////// + static SrcFinfo1< double >* activationOut(); + static const Cinfo* initCinfo(); + +private: - /** - * Record arrival of a new spike event. The 'time' is time for - * eventual arrival of the spike, and is typically well in the - * future. The index specifies which synapse the spike came to. - */ - virtual void addSpike( - unsigned int index, double time, double weight ) = 0; - virtual double getTopSpike( unsigned int index ) const = 0; - //////////////////////////////////////////////////////////////// - // Virtual func definitions for fields. - //////////////////////////////////////////////////////////////// - virtual void vSetNumSynapses( unsigned int num ) = 0; - virtual unsigned int vGetNumSynapses() const = 0; - virtual Synapse* vGetSynapse( unsigned int i ) = 0; - virtual void vProcess( const Eref& e, ProcPtr p ) = 0; - virtual void vReinit( const Eref& e, ProcPtr p ) = 0; - //////////////////////////////////////////////////////////////// - static SrcFinfo1< double >* activationOut(); - static const Cinfo* initCinfo(); - private: }; #endif // _SYN_HANDLER_BASE_H diff --git a/moose-core/synapse/testSynapse.cpp b/moose-core/synapse/testSynapse.cpp index 600d7ff3fe913565d4fc4b7dc8f9b52ac73d41ae..427f08b1c7a541411e5f7085a2b72d85e1dedf4f 100644 --- a/moose-core/synapse/testSynapse.cpp +++ b/moose-core/synapse/testSynapse.cpp @@ -18,7 +18,6 @@ #include "RollingMatrix.h" #include "SeqSynHandler.h" #include "../shell/Shell.h" -#include "../randnum/randnum.h" double doCorrel( RollingMatrix& rm, vector< vector< double >> & kernel ) { diff --git a/moose-core/tests/python/OSC_diff_vols.g b/moose-core/tests/python/OSC_diff_vols.g new file mode 100644 index 0000000000000000000000000000000000000000..d7166be273ca0af5e73079b31d625eb311f4dc10 --- /dev/null +++ b/moose-core/tests/python/OSC_diff_vols.g @@ -0,0 +1,219 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Tue Jan 21 14:05:52 2014 + +include kkit {argv 1} + +FASTDT = 0.0001 +SIMDT = 0.005 +CONTROLDT = 5 +PLOTDT = 10 +MAXTIME = 2500 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 1 +DEFAULT_VOL = 1e-20 +VERSION = 11.0 +setfield /file/modpath value /home2/bhalla/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 9.9998e-20 3 sphere "" white black 0 \ + 0 0 +simundump geometry /kinetics/geometry[1] 0 9.9998e-21 3 sphere "" white black \ + 0 0 0 +simundump geometry /kinetics/geometry[2] 0 1e-20 3 sphere "" white black 0 0 \ + 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump text /kinetics/geometry[1]/notes 0 "" +call /kinetics/geometry[1]/notes LOAD \ +"" +simundump text /kinetics/geometry[2]/notes 0 "" +call /kinetics/geometry[2]/notes LOAD \ +"" +simundump kreac /kinetics/exo 0 0.005 0 "" white black 3 9 0 +simundump text /kinetics/exo/notes 0 "" +call /kinetics/exo/notes LOAD \ +"" +simundump kreac /kinetics/endo 0 0.01 0 "" white black -6 11 0 +simundump text /kinetics/endo/notes 0 "" +call /kinetics/endo/notes LOAD \ +"" +simundump group /kinetics/B 0 yellow black x 0 0 "" Bulk defaultfile.g 0 0 0 \ + -7 6 0 +simundump text /kinetics/B/notes 0 "" +call /kinetics/B/notes LOAD \ +"" +simundump kpool /kinetics/B/P 0 0 0.1 0.1 0.6 0.6 0 0 6 0 /kinetics/geometry \ + 4 yellow -2 2 0 +simundump text /kinetics/B/P/notes 0 "" +call /kinetics/B/P/notes LOAD \ +"" +simundump kenz /kinetics/B/P/kenz 0 0 0 0 0 6 16.667 4 1 0 0 "" red 4 "" -2 0 \ + 0 +simundump text /kinetics/B/P/kenz/notes 0 "" +call /kinetics/B/P/kenz/notes LOAD \ +"" +simundump kreac /kinetics/B/basal 0 0.01 0 "" white yellow -4 -4 0 +simundump text /kinetics/B/basal/notes 0 "" +call /kinetics/B/basal/notes LOAD \ +"" +simundump kpool /kinetics/B/M 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry 62 \ + yellow -5 7 0 +simundump text /kinetics/B/M/notes 0 "" +call /kinetics/B/M/notes LOAD \ +"" +simundump kpool /kinetics/B/M* 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry 28 \ + yellow 2 2 0 +simundump text /kinetics/B/M*/notes 0 "" +call /kinetics/B/M*/notes LOAD \ +"" +simundump kenz /kinetics/B/M*/kenz 0 0 0 0 0 59.999 0.41667 2 0.5 0 0 "" red \ + 28 "" 1 6 0 +simundump text /kinetics/B/M*/kenz/notes 0 "" +call /kinetics/B/M*/kenz/notes LOAD \ +"" +simundump group /kinetics/A 0 16 black x 0 0 "" PSD defaultfile.g 0 0 0 -5 16 \ + 0 +simundump text /kinetics/A/notes 0 "" +call /kinetics/A/notes LOAD \ +"" +simundump kreac /kinetics/A/basal 0 0.01 0 "" white 16 -1 8 0 +simundump text /kinetics/A/basal/notes 0 "" +call /kinetics/A/basal/notes LOAD \ +"" +simundump kpool /kinetics/A/Stot 0 0 0 1.75 21 0 0 0 12 0 \ + /kinetics/geometry[2] 41 16 0 24 0 +simundump text /kinetics/A/Stot/notes 0 "" +call /kinetics/A/Stot/notes LOAD \ +"" +simundump kpool /kinetics/A/P 0 0 0.049999 0.049999 0.59999 0.59999 0 0 12 0 \ + /kinetics/geometry[1] 3 16 -1 11 0 +simundump text /kinetics/A/P/notes 0 "" +call /kinetics/A/P/notes LOAD \ +"" +simundump kenz /kinetics/A/P/kenz 0 0 0 0 0 5.9999 16.667 4 1 0 0 "" red 3 "" \ + -1 13 0 +simundump text /kinetics/A/P/kenz/notes 0 "" +call /kinetics/A/P/kenz/notes LOAD \ +"" +simundump kpool /kinetics/A/M* 0 0 0 0 0 0 0 0 12 0 /kinetics/geometry 47 16 \ + 4 19 0 +simundump text /kinetics/A/M*/notes 0 "" +call /kinetics/A/M*/notes LOAD \ +"" +simundump kenz /kinetics/A/M*/kenz 0 0 0 0 0 5.9999 0.41667 2 0.5 0 0 "" red \ + 57 "" -1 18 0 +simundump text /kinetics/A/M*/kenz/notes 0 "" +call /kinetics/A/M*/kenz/notes LOAD \ +"" +simundump kpool /kinetics/A/M 0 0 1.75 1.75 21 21 0 0 12 0 /kinetics/geometry \ + 53 16 -4 17 0 +simundump text /kinetics/A/M/notes 0 "" +call /kinetics/A/M/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 2500 0.001 3 0 +simundump xgraph /graphs/conc2 0 0 2500 0 5 0 +simundump xplot /graphs/conc1/M.Co 3 524288 \ + "delete_plot.w <s> <d>; edit_plot.D <w>" 53 0 0 1 +simundump xplot /graphs/conc1/M*.Co 3 524288 \ + "delete_plot.w <s> <d>; edit_plot.D <w>" 47 0 0 1 +simundump xplot /graphs/conc2/M.Co 3 524288 \ + "delete_plot.w <s> <d>; edit_plot.D <w>" 62 0 0 1 +simundump xplot /graphs/conc2/M*.Co 3 524288 \ + "delete_plot.w <s> <d>; edit_plot.D <w>" 28 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 2500 0 1 0 +simundump xgraph /moregraphs/conc4 0 0 2500 0 1 0 +simundump xcoredraw /edit/draw 0 -9 6 -6 26 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D <v>; drag_from_edit.w <d> <S> <x> <y> <z>" auto 0.6 +simundump xtext /file/notes 0 1 +xtextload /file/notes \ +"21 Jan 2014." \ +"Using " \ +"different volumes for the two compartments, based on OSC_Cspace.g" +addmsg /kinetics/B/M* /kinetics/exo SUBSTRATE n +addmsg /kinetics/A/M* /kinetics/exo PRODUCT n +addmsg /kinetics/A/M /kinetics/endo SUBSTRATE n +addmsg /kinetics/B/M /kinetics/endo PRODUCT n +addmsg /kinetics/B/P/kenz /kinetics/B/P REAC eA B +addmsg /kinetics/B/P /kinetics/B/P/kenz ENZYME n +addmsg /kinetics/B/M* /kinetics/B/P/kenz SUBSTRATE n +addmsg /kinetics/B/M /kinetics/B/basal SUBSTRATE n +addmsg /kinetics/B/M* /kinetics/B/basal PRODUCT n +addmsg /kinetics/B/basal /kinetics/B/M REAC A B +addmsg /kinetics/B/P/kenz /kinetics/B/M MM_PRD pA +addmsg /kinetics/B/M*/kenz /kinetics/B/M REAC sA B +addmsg /kinetics/endo /kinetics/B/M REAC B A +addmsg /kinetics/B/basal /kinetics/B/M* REAC B A +addmsg /kinetics/B/P/kenz /kinetics/B/M* REAC sA B +addmsg /kinetics/B/M*/kenz /kinetics/B/M* REAC eA B +addmsg /kinetics/B/M*/kenz /kinetics/B/M* MM_PRD pA +addmsg /kinetics/exo /kinetics/B/M* REAC A B +addmsg /kinetics/B/M* /kinetics/B/M*/kenz ENZYME n +addmsg /kinetics/B/M /kinetics/B/M*/kenz SUBSTRATE n +addmsg /kinetics/A/M /kinetics/A/basal SUBSTRATE n +addmsg /kinetics/A/M* /kinetics/A/basal PRODUCT n +addmsg /kinetics/A/M /kinetics/A/Stot SUMTOTAL n nInit +addmsg /kinetics/A/M* /kinetics/A/Stot SUMTOTAL n nInit +addmsg /kinetics/A/M*/kenz /kinetics/A/Stot SUMTOTAL nComplex nComplexInit +addmsg /kinetics/A/P/kenz /kinetics/A/Stot SUMTOTAL nComplex nComplexInit +addmsg /kinetics/A/M*/kenz /kinetics/A/Stot SUMTOTAL nComplex nComplexInit +addmsg /kinetics/A/P/kenz /kinetics/A/P REAC eA B +addmsg /kinetics/A/P /kinetics/A/P/kenz ENZYME n +addmsg /kinetics/A/M* /kinetics/A/P/kenz SUBSTRATE n +addmsg /kinetics/A/M*/kenz /kinetics/A/M* MM_PRD pA +addmsg /kinetics/A/P/kenz /kinetics/A/M* REAC sA B +addmsg /kinetics/A/basal /kinetics/A/M* REAC B A +addmsg /kinetics/A/M*/kenz /kinetics/A/M* REAC eA B +addmsg /kinetics/exo /kinetics/A/M* REAC B A +addmsg /kinetics/A/M /kinetics/A/M*/kenz SUBSTRATE n +addmsg /kinetics/A/M* /kinetics/A/M*/kenz ENZYME n +addmsg /kinetics/A/M*/kenz /kinetics/A/M REAC sA B +addmsg /kinetics/A/P/kenz /kinetics/A/M MM_PRD pA +addmsg /kinetics/A/basal /kinetics/A/M REAC A B +addmsg /kinetics/endo /kinetics/A/M REAC A B +addmsg /kinetics/A/M /graphs/conc1/M.Co PLOT Co *M.Co *53 +addmsg /kinetics/A/M* /graphs/conc1/M*.Co PLOT Co *M*.Co *47 +addmsg /kinetics/B/M /graphs/conc2/M.Co PLOT Co *M.Co *62 +addmsg /kinetics/B/M* /graphs/conc2/M*.Co PLOT Co *M*.Co *28 +enddump +// End of dump + +complete_loading diff --git a/moose-core/tests/python/fixXreacs.py b/moose-core/tests/python/fixXreacs.py new file mode 100644 index 0000000000000000000000000000000000000000..7a68ed9b6c89a0bccf7e95e9b4108270c115b294 --- /dev/null +++ b/moose-core/tests/python/fixXreacs.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +#################################################################### +# fixXreacs.py +# The program is meant to take a model and reconfigure any cross-compartment +# reactions so that they are split into portions on either side coupled +# either by diffusion, or by a reaction-driven translocation process. +# +# Copyright (C) Upinder S. Bhalla 2018 +# This program is free software. It is licensed under the terms of +# GPL version 3 or later at your discretion. +# This program carries no warranty whatsoever. +#################################################################### + + +import sys +import moose + +msgSeparator = "_xMsg_" + +def findCompt( elm ): + elm = moose.element( elm ) + pa = elm.parent + while pa.path != '/': + if moose.Neutral(pa).isA[ 'ChemCompt' ]: + return pa.path + pa = pa.parent + print( 'Error: No compartment parent found for ' + elm.path ) + return '/' + +# http://stackoverflow.com/q/3844948/ +def checkEqual(lst): + return not lst or lst.count(lst[0]) == len(lst) + +def findXreacs( basepath, reacType ): + reacs = moose.wildcardFind( basepath + '/##[ISA=' + reacType + 'Base]' ) + ret = [] + for i in reacs: + reacc = findCompt( i ) + subs = i.neighbors['subOut'] + prds = i.neighbors['prdOut'] + subc = [findCompt(j) for j in subs] + prdc = [findCompt(j) for j in prds] + + enzc = [] + if reacType == 'Enz': + enzc = [reacc] + if not checkEqual( subc + prdc + enzc ): + ret.append( [i, reacc, subs, subc, prds, prdc ]) + return ret + +def removeEnzFromPool( pool ): + kids = moose.wildcardFind( pool.path + "/#" ) + for i in kids: + if i.isA[ 'EnzBase' ]: + moose.delete( i ) + elif i.isA[ 'Function' ]: + moose.delete( i ) + +# If a pool is not in the same compt as reac, make a proxy in the reac +# compt, connect it up, and disconnect the one in the old compt. +def proxify( reac, reacc, direction, pool, poolc ): + reacc_elm = moose.element( reacc ) + reac_elm = moose.element( reac ) + # Preserve the rates which were set up for the x-compt reacn + #moose.showfield( reac ) + dupname = pool.name + '_xfer_' + moose.element(poolc).name + #print "#############", pool, dupname, poolc + if moose.exists( reacc + '/' + dupname ): + duppool = moose.element( reacc + '/' + dupname ) + else: + # This also deals with cases where the duppool is buffered. + duppool = moose.copy(pool, reacc_elm, dupname ) + duppool.diffConst = 0 # diffusion only happens in original compt + removeEnzFromPool( duppool ) + disconnectReactant( reac, pool, duppool ) + moose.connect( reac, direction, duppool, 'reac' ) + #moose.showfield( reac ) + #moose.showmsg( reac ) + +def enzProxify( enz, enzc, direction, pool, poolc ): + if enzc == poolc: + return + enze = moose.element( enz ) + # kcat and k2 are indept of volume, just time^-1 + km = enze.numKm + proxify( enz, enzc, direction, pool, poolc ) + enze.numKm = km + +def reacProxify( reac, reacc, direction, pool, poolc ): + if reacc == poolc: + return + reac_elm = moose.element( reac ) + kf = reac_elm.numKf + kb = reac_elm.numKb + proxify( reac, reacc, direction, pool, poolc ) + reac_elm.numKf = kf + reac_elm.numKb = kb + +def identifyMsg( src, srcOut, dest ): + if src.isA[ 'ReacBase' ] or src.isA[ 'EnzBase' ]: + if srcOut == 'subOut': + return msgSeparator + src.path + ' sub ' + dest.path + ' reac' + if srcOut == 'prdOut': + return msgSeparator + src.path + ' prd ' + dest.path + ' reac' + return '' + +def disconnectReactant( reacOrEnz, reactant, duppool ): + outMsgs = reacOrEnz.msgOut + infoPath = duppool.path + '/info' + if moose.exists( infoPath ): + info = moose.element( infoPath ) + else: + info = moose.Annotator( infoPath ) + + #moose.le( reactant ) + notes = "" + #moose.showmsg( reacOrEnz ) + for i in outMsgs: + #print "killing msg from {} to {}\nfor {} and {}".format( reacOrEnz.path, reactant.path, i.srcFieldsOnE1[0], i.srcFieldsOnE2[0] ) + if i.e1 == reactant: + msgStr = identifyMsg( i.e2, i.e2.srcFieldsOnE2[0], i.e1 ) + if len( msgStr ) > 0: + notes += msgStr + moose.delete( i ) + elif i.e2 == reactant: + msgStr = identifyMsg( i.e1[0], i.srcFieldsOnE1[0], i.e2[0] ) + if len( msgStr ) > 0: + notes += msgStr + moose.delete( i ) + #print "MSGS to rebuild:", notes + info.notes += notes + +def fixXreacs( basepath ): + xr = findXreacs( basepath, 'Reac' ) + xe = findXreacs( basepath, 'Enz' ) + + for i in (xr): + reac, reacc, subs, subc, prds, prdc = i + for j in range( len( subs )): + reacProxify( reac, reacc, 'sub', subs[j], subc[j] ) + for j in range( len( prds )): + reacProxify( reac, reacc, 'prd', prds[j], prdc[j] ) + + for i in (xe): + reac, reacc, subs, subc, prds, prdc = i + for j in range( len( subs )): + enzProxify( reac, reacc, 'sub', subs[j], subc[j] ) + for j in range( len( prds )): + enzProxify( reac, reacc, 'prd', prds[j], prdc[j] ) + +##################################################################### + +def getOldRates( msgs ): + if len( msgs ) > 1 : + m1 = msgs[1].split( msgSeparator )[0] + elm = moose.element( m1.split( ' ' )[0] ) + if elm.isA[ 'ReacBase' ]: + return [elm.numKf, elm.numKb] + elif elm.isA[ 'EnzBase' ]: + return [elm.numKm,] + print( "Warning: getOldRates did not have any messages" ) + return [0,] + +def restoreOldRates( oldRates, msgs ): + #print oldRates, msgs + if len( msgs ) > 1 : + m1 = msgs[1].split( msgSeparator )[0] + elm = moose.element( m1.split( ' ' )[0] ) + if elm.isA[ 'ReacBase' ]: + elm.numKf = oldRates[0] + elm.numKb = oldRates[1] + elif elm.isA[ 'enzBase' ]: + elm.numKm = oldRates[0] + + + +def restoreXreacs( basepath ): + proxyInfo = moose.wildcardFind( basepath + "/##/#_xfer_#/info" ) + for i in proxyInfo: + msgs = i.notes.split( msgSeparator ) + oldRates = getOldRates( msgs ) + #print( "Deleting {}".format( i.parent.path ) ) + #print msgs + moose.delete( i.parent ) + for j in msgs: + if len( j ) > 0: + args = j.split( ' ' ) + assert( len( args ) == 4 ) + #moose.showfield( args[0] ) + moose.connect( args[0], args[1], args[2], args[3] ) + #print( "Reconnecting {}".format( args ) ) + #moose.showfield( args[0] ) + restoreOldRates( oldRates, msgs ) + diff --git a/moose-core/tests/python/params.py b/moose-core/tests/python/params.py index 1feacecc91b9a7de77d801b1bf26722d1196a65f..bd3bacae5b789c1b2ed18745fa3c8e6e912373d1 100644 --- a/moose-core/tests/python/params.py +++ b/moose-core/tests/python/params.py @@ -1,27 +1,63 @@ # -*- coding: utf-8 -*- -t_stop = 10 -dend_diameter = 2.2627398e-6 -dend_length = 1.131369936e-6 -Cm = 4.021231698e-12 -Rm = 1865100032 -Em = -0.07100000232 -Vm_0 = -0.0705 -dt = 50e-6 -spines_no = 0 -difshell_no = 2 -difshell_name = "Ca_shell" -Ca_basal = 50e-6 -Ca_initial = Ca_basal*200 -dca = 200.0e-12 -difbuff_no = 1 -difbuff_name = "Buff" -btotal = 80.0e-3 -kf = 0.028e6 -kb = 19.6 -d = 66e-12 -inject = 0.1e-9 -gbar = 1 -#MMpump -km = 0.3e-3 -kcat = 85e-22 -pumps = 1 +"""params.py + +Parameters used in this model + +These parameters are from paper Miller et. al. "The stability of CaMKII +switch" + +""" + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2015, Dilawar Singh and NCBS Bangalore" +__credits__ = ["NCBS Bangalore"] +__license__ = "GNU GPL" +__version__ = "1.0.0" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" +__status__ = "Development" + + +run_time = 30 +N_CaMK = 10 +N_PP1 = 100 +num_switch = 1 +voxel_length = 125e-9 +num_voxels = 1 + +diff_consts = { 'x' : 1e-13, 'y' : 1e-13, 'pp1' : 1e-13 } + +conc_i1_free = 0.1e-3 +act_CaN = 1.0 +act_PKA = 1.0 + +# Michaelis constant of protein phosphatase. +# 0.4 um to 2.0 uM have been used. Miller uses 0.2 um. The switch shows +# bistability of these ranges. We have taken the largest Km (or slowest) first +# step in dephosphorylation. +K_M = 10e-3 +k_2 = 10.0 + +# Hill coefficientfor Ca++ activation of CaMKII +K_H1 = 0.7e-3 +K_H2 = 0.3e-3 + +k_1 = 1.5 +k_3 = 100e3 +k_4 = 0.001 +K_I = 1e-6 + +rate_loosex = 0.1 +rate_loosey = 0.1 +rate_gainx = 1 +rate_gainy = 1 + +turnover_rate = 1/(30*3600.0) +v_1 = 1.268e-5 +v_2 = 4.36e-3 +phosphatase_inhibit = 280.0 +vi = phosphatase_inhibit + +## Calcium input expression. +ca_basal = 80e-6 +ca_expr = "(fmod(t,4)<2)?{0}:({0}*(1+0.5*rand(-1)))".format( ca_basal ) diff --git a/moose-core/tests/python/testXchan1.py b/moose-core/tests/python/testXchan1.py new file mode 100644 index 0000000000000000000000000000000000000000..1bcc130b6e694a3823ad9be4cef4b88630e81379 --- /dev/null +++ b/moose-core/tests/python/testXchan1.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here test ConcChan. We set up a channel and a pump and run two tests. +## First we have zero flux through the pump and check that the conc +## equalizes on both sides of the membrane. Then we change the Kf of +## the pump to a value designed to give twice the conc In as Out. +## The system is a 1-voxel cyl compt and an internal endoMesh, having a +## volume = 1/8 of the cylinder. +## \ +## COMPT: s ----> / s :ENDO +## s =chan= s +## \ +## +## This becomes: +## \ +## COMPT: s ----> s_xfer_endo / s :ENDO +## s =chan= s +## \ +## +######################################################################### + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +print( '[INFO ] Using moose from %s, %s' % (moose.__file__, moose.version()) ) +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + # Note that the chanPool must be on the 'In' compartment. + #chanPool = moose.Pool( '/model/compartment/chanPool' ) + #chan = moose.ConcChan( '/model/compartment/chanPool/chan' ) + chanPool = moose.Pool( '/model/endo/chanPool' ) + chan = moose.ConcChan( '/model/endo/chanPool/chan' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + moose.connect( chanPool, 'nOut', chan, 'setNumChan' ) + moose.connect( chan, 'out', s, 'reac' ) + moose.connect( chan, 'in', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.0 # 0.02/sec + rXfer.Kb = 0.0 # + s.concInit = 0.001 + chanPool.nInit = 1000.0 + # Flux (#/s) = permeability * N * (#out/vol_out - #in/vol_in) + chan.permeability = 0.1 * chanPool.volume / chanPool.nInit + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + eksolve.method = 'gsl' + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def doPlot( ax, i, label ): + scale = 1 + if i > 3: + scale = 1000 # Just to plot in uM. + plot1 = '/model/plot' + str(i) + plot2 = '/model/plot' + str(i+1) + plot3 = '/model/plot' + str(i+2) + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector * scale + v2 = moose.element(plot2).vector * scale + v3 = moose.element(plot3).vector * scale + ax.plot( v1, label='s' ) + ax.plot( v2, 'x',label='es' ) + ax.plot( v3, label='xfer' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + displayInterval = 2 + makeModel() + for i in range( 10, 18 ): + moose.setClock( i, 0.01 ) + moose.reinit() + moose.start( runtime ) + s = moose.element( '/model/compartment/s' ) + es = moose.element( '/model/endo/s' ) + assert almostEq( s.conc, es.conc ), 'Asserting %g=%g' % (s.conc, es.conc) + # We go for concEndo = 2x concOut. Then + # We already know volIn = volOut/8 + # #in/volIn = 2x #out/volOut + # #in/volIn = 2x #out/(8*volIn) + # so #in = #out/4 + # From consv, #in + #out = nInit + # so 5/4#out = nInit => + # #out = 0.8*nInit; #in = 0.2*nInit + # + # flux = perm * nChan * (0.8nInit/volOut - 0.2nInit/(volOut/8) ) = + # perm * (nChan*nInit/volOut) * (0.8 - 0.2*8) = + # perm * (nChan*nInit/volOut) * (-0.8) + # + # This has to be balanced by flux = numKf * nOut = numKf * 0.8 * nInit + # So 0.8*numKf*nInit = 0.8*perm*nChan*nInit/volOut + + # Note that chan.permeability = 0.1*chanPool.volume / chanPool.nInit + + # so numKf = perm*nChan/volOut = (0.1*volIn/nChan)*nChan/volOut=0.1/8 + # + rXfer = moose.element( '/model/compartment/rXfer' ) + rXfer.numKf = 0.1/8.0 + moose.start( runtime ) + assert( almostEq( 2 * s.conc, es.conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, 1, '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, 4, 'conc (uM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXdiff1.py b/moose-core/tests/python/testXdiff1.py new file mode 100644 index 0000000000000000000000000000000000000000..bbf73e8715f99c14b74d6dc4b638a61798370213 --- /dev/null +++ b/moose-core/tests/python/testXdiff1.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here test diffusion across a junction. We set up a pump and change its +## rate to do a check on the calculation of the diffusion rate separate +## from the verification that diffusion gives equal concs on either side. +## The system is a ## 1-voxel cyl compt and an internal endoMesh, +## having a volume = 1/8 of the parent cylinder.. +## \ +## COMPT: s ----> / s :ENDO +## s =diffn= s +## \ +## +## This becomes: +## \ +## COMPT: s ----> s_xfer_endo / s :ENDO +# s =diffn= s +## \ +## +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +diffConst = 1e-16 + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = False + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + #print( "Volume ratio = {}".format( volRatio ) ) + rXfer.Kf = 0.0 # 0.02/sec + rXfer.Kb = 0.0 # + s.concInit = 0.001 + s.diffConst = diffConst + es.diffConst = diffConst + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def doPlot( ax, i, label ): + scale = 1 + if i > 3: + scale = 1000 # Just to plot in uM. + plot1 = '/model/plot' + str(i) + plot2 = '/model/plot' + str(i+1) + plot3 = '/model/plot' + str(i+2) + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector * scale + v2 = moose.element(plot2).vector * scale + v3 = moose.element(plot3).vector * scale + ax.plot( v1, label='s' ) + ax.plot( v2, 'x',label='es' ) + ax.plot( v3, label='xfer' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + makeModel() + for i in range( 10, 18 ): + moose.setClock( i, 0.01 ) + moose.reinit() + moose.start( runtime ) + s = moose.element( '/model/compartment/s' ) + es = moose.element( '/model/endo/s' ) + assert( almostEq( s.conc, es.conc ) ) + # We go for concEndo = 2x concOut. Then + # We already know volIn = volOut/8 + # #in/volIn = 2x #out/volOut + # #in/volIn = 2x #out/(8*volIn) + # so #in = #out/4 + # From consv, #in + #out = nInit + # so 5/4#out = nInit => + # #out = 0.8*nInit; #in = 0.2*nInit + # + # Diffn flux = D * (xa/L) * (0.8nInit/volOut - 0.2nInit/(volOut/8) ) + # = -D * (xa/L) * (nInit/volOut) * 0.8 + # We can obtain xa and L from the endo/mesh + # + # This has to be balanced by flux = numKf * nOut = numKf * 0.8 * nInit + # So 0.8*numKf*nInit = 0.8*(D.Xa/L)*(nInit/volOut) + # So numKf = D.Xa/(L*volOut) + # + rXfer = moose.element( '/model/compartment/rXfer' ) + endo = moose.element( '/model/endo' ) + compt = moose.element( '/model/compartment' ) + endoA = endo.aScale * pow( compt.volume, endo.aPower ) + rXfer.numKf = 2.0*diffConst*endoA/(compt.r0*compt.volume) + moose.start( runtime ) + assert( almostEq( 2 * s.conc, es.conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, 1, '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, 4, 'conc (uM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXenz1.py b/moose-core/tests/python/testXenz1.py new file mode 100644 index 0000000000000000000000000000000000000000..b359d44ebfc17abf0928ccff18e1e01964671ebf --- /dev/null +++ b/moose-core/tests/python/testXenz1.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## +## Endo / Compartment +## \ +## sub--enz-/-----> prd +## sub<-----\----- prd +## / +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +subInit = 0.002 +eInit = 0.001 +Km = 0.001 +kcat = 0.2 +Kf = 0.1 + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + prd = moose.Pool( '/model/compartment/prd' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + sub = moose.Pool( '/model/endo/sub' ) + enzPool = moose.Pool( '/model/endo/enzPool' ) + enzPool.concInit = eInit + enz = moose.MMenz( '/model/endo/enzPool/enz' ) + ##################################################################### + moose.connect( enz, 'sub', sub, 'reac' ) + moose.connect( enz, 'prd', prd, 'reac' ) + moose.connect( enzPool, 'nOut', enz, 'enzDest' ) + moose.connect( rXfer, 'sub', prd, 'reac' ) + moose.connect( rXfer, 'prd', sub, 'reac' ) + rXfer.Kf = Kf # 0.04/sec + rXfer.Kb = 0.0 # 0.02/sec + enz.Km = Km + enz.kcat = kcat + # v = es.kcat/(s+Km) + # v = Kf * conc. + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + sub.vec.concInit = subInit + enzPool.vec.concInit = eInit + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 3 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', sub, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', prd, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', sub, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', prd, 'getConc' ) + +def doPlot( ax, plot1, plot2, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + ax.plot( v1, label='sub' ) + ax.plot( v2, label='prd' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + for i in range( 10, 18 ): + moose.setClock( i, 0.001 ) + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/prd' ).n, + moose.element( '/model/endo/sub' ).n ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs2.py b/moose-core/tests/python/testXreacs2.py new file mode 100644 index 0000000000000000000000000000000000000000..289c2b24670437c9197d05d7fdcf9a8b3f87264a --- /dev/null +++ b/moose-core/tests/python/testXreacs2.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +import os +import matplotlib as mpl +import matplotlib.pyplot as plt +mpl.rcParams['text.usetex'] = False +import moose +import numpy as np +import fixXreacs + +def countCrossings( plot, thresh ): + vec = moose.element( plot ).vector + #print (vec[:-1] < thresh) + return sum( (vec[:-1] < thresh) * (vec[1:] >= thresh ) ) + +def main( standalone = False ): + mfile = os.path.join( os.path.dirname( __file__), 'OSC_diff_vols.g' ) + runtime = 4000.0 + modelId = moose.loadModel( mfile, 'model', 'ee' ) + kin = moose.element( '/model/kinetics' ) + compt1 = moose.element( '/model/compartment_1' ) + compt1.x1 += kin.x1 + compt1.x0 += kin.x1 + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + + ks1 = moose.Ksolve( '/model/kinetics/ksolve' ) + ds1 = moose.Dsolve( '/model/kinetics/dsolve' ) + s1 = moose.Stoich( '/model/kinetics/stoich' ) + s1.compartment = moose.element( '/model/kinetics' ) + s1.ksolve = ks1 + s1.dsolve = ds1 + s1.path = '/model/kinetics/##' + + ks2 = moose.Ksolve( '/model/compartment_1/ksolve' ) + ds2 = moose.Dsolve( '/model/compartment_1/dsolve' ) + s2 = moose.Stoich( '/model/compartment_1/stoich' ) + s2.compartment = moose.element( '/model/compartment_1' ) + s2.ksolve = ks2 + s2.dsolve = ds2 + s2.path = '/model/compartment_1/##' + + ds2.buildMeshJunctions( ds1 ) + + moose.reinit() + moose.start( runtime ) + # I don't have an analytic way to assess oscillations + assert( countCrossings( '/model/graphs/conc2/M.Co', 0.001 ) == 4 ) + + if standalone: + # Display all plots. + for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): + t = np.arange( 0, x.vector.size, 1 ) * x.dt + plt.plot( t, x.vector, label=x.name ) + plt.legend() + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs3.py b/moose-core/tests/python/testXreacs3.py new file mode 100644 index 0000000000000000000000000000000000000000..4e5ef170d23a2acf315fff969eab69f63bc1f999 --- /dev/null +++ b/moose-core/tests/python/testXreacs3.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here we set up equal Kf and Kb in a reversible reaction across a +## 1-voxel cyl compt and an internal endoMesh, having a smaller volume. +## \ +## COMPT: s <===> / s :ENDO +## \ +## +## This becomes: +## \ +## COMPT: s <===> s_xfer_endo / s :ENDO +## \ +## +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.02 # 0.01/sec + rXfer.Kb = 0.02 # 1/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def doPlot( ax, i, label ): + plot1 = '/model/plot' + str(i) + plot2 = '/model/plot' + str(i+1) + plot3 = '/model/plot' + str(i+2) + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + v3 = moose.element(plot3).vector + ax.plot( v1, label='s' ) + ax.plot( v2, 'x',label='es' ) + ax.plot( v3, label='xfer' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, 1, '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, 4, 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs4.py b/moose-core/tests/python/testXreacs4.py new file mode 100644 index 0000000000000000000000000000000000000000..4fd440076aede4ec9f14e60f8f7dbb8b8e0c8ee2 --- /dev/null +++ b/moose-core/tests/python/testXreacs4.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.02 # 0.02/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def doPlot( ax, plot1, plot2, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + ax.plot( v1, label='s' ) + ax.plot( v2, label='es' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) + plt.show() + + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs4a.py b/moose-core/tests/python/testXreacs4a.py new file mode 100644 index 0000000000000000000000000000000000000000..2fe009e9e67759f3cebb95152b2da48052ebed8e --- /dev/null +++ b/moose-core/tests/python/testXreacs4a.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + rXfer = moose.Reac( '/model/endo/rXfer' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.02 # 0.02/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 1 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def doPlot( ax, plot1, plot2, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + ax.plot( v1, label='s' ) + ax.plot( v2, label='es' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 200 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs5.py b/moose-core/tests/python/testXreacs5.py new file mode 100644 index 0000000000000000000000000000000000000000..e46bc45906757f85b060b427a84856a57ed24244 --- /dev/null +++ b/moose-core/tests/python/testXreacs5.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + erXfer = moose.Reac( '/model/endo/erXfer' ) + ##################################################################### + moose.connect( erXfer, 'sub', es, 'reac' ) + moose.connect( erXfer, 'prd', s, 'reac' ) + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.0 # 0.00/sec + erXfer.Kf = 0.16 # 0.16/sec + erXfer.Kb = 0.0 # 0.00/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def doPlot( ax, plot1, plot2, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + ax.plot( v1, label='s' ) + ax.plot( v2, label='es' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + for i in range( 10, 18): + moose.setClock( i, 0.001 ) + runtime = 100 + makeModel() + moose.reinit() + moose.start( runtime ) + + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs5a.py b/moose-core/tests/python/testXreacs5a.py new file mode 100644 index 0000000000000000000000000000000000000000..330419ea1cae499105e168c6324b2f9b318e2053 --- /dev/null +++ b/moose-core/tests/python/testXreacs5a.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + erXfer = moose.Reac( '/model/compartment/erXfer' ) + ##################################################################### + moose.connect( erXfer, 'sub', es, 'reac' ) + moose.connect( erXfer, 'prd', s, 'reac' ) + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.0 # 0.02/sec + erXfer.Kf = 0.02 # 0.04/sec + erXfer.Kb = 0.0 # 0.02/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + rx = moose.element( '/model/compartment/rXfer' ) + erx = moose.element( '/model/compartment/erXfer' ) + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def doPlot( ax, plot1, plot2, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + ax.plot( v1, label='s' ) + ax.plot( v2, label='es' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 200 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).n, + moose.element( '/model/endo/s' ).n ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs6.py b/moose-core/tests/python/testXreacs6.py new file mode 100644 index 0000000000000000000000000000000000000000..7edb514d9185d6cf3aeba3f8d8280362801950da --- /dev/null +++ b/moose-core/tests/python/testXreacs6.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2018 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU General Public License version 3 or later. +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + t = moose.Pool( '/model/compartment/t' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + et = moose.Pool( '/model/endo/t' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'sub', t, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + moose.connect( rXfer, 'prd', et, 'reac' ) + rXfer.Kf = 0.02 # 0.02/mM/sec + rXfer.Kb = 0.02 # 0.02/mM/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 4 ) + s.vec.concInit = [1]*num + t.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def doPlot( ax, plot1, plot2, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + ax.plot( v1, label='s' ) + ax.plot( v2, label='es' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + for i in range( 10, 18): + moose.setClock( i, 0.01 ) + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + + assert( almostEq( moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs7.py b/moose-core/tests/python/testXreacs7.py new file mode 100644 index 0000000000000000000000000000000000000000..b55de2686be921c2deb174c4149ba2091d545f56 --- /dev/null +++ b/moose-core/tests/python/testXreacs7.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2018 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU General Public License version 3 or later. +## See the file COPYING.LIB for the full notice. +## +## This file makes u + t <=====> s where u is in a different compt from t,s +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + u = moose.Pool( '/model/compartment/u' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + rXfer = moose.Reac( '/model/endo/rXfer' ) + et = moose.Pool( '/model/endo/t' ) + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', u, 'reac' ) + moose.connect( rXfer, 'sub', et, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + u.concInit = 1.0 + et.concInit = 1.0 + + ##################################################################### + # [u0] = 1 in compt, [t0] = 1 in endo, [s0] = 0 + # [u] + [s]/8 = [u0] ; [t] + [s] = [t0]; nu + ns = nu0, nt + ns = nt0 + # At equil, numKf*nu*nt = numKb*ns + # Express all # in terms of ns. + # nu = nu0-ns; nt = nt0-ns Also, nu0 = 8*nt0 + # So numKf*(nu0-ns)*(nt0-ns) = numKb*ns + # Target level is nt = ns = nt0/2 + # So numKf*( 8nt0 - nt0/2)*nt0/2 = numKb*nt0/2 + # So 7.5*nt0 = numKb/numKf + rXfer.numKb = 0.1 + rXfer.numKf = 0.1/(7.5 * et.nInit) + #print( "Rates = {}, {}".format( rXfer.Kf, rXfer.Kb )) + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/compartment/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 1 ) + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 3 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', u, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', et, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', es, 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', u, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', et, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', es, 'getConc' ) + +def doPlot( ax, i, label ): + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element('/model/plot' + str(i)).vector + v2 = moose.element('/model/plot' + str(i+1)).vector + v3 = moose.element('/model/plot' + str(i+2)).vector + ax.plot( v1, label='u' ) + ax.plot( v2, label='et' ) + ax.plot( v3, label='es' ) + ax.plot( np.array( v1 ) + np.array( v3 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + + assert( almostEq( moose.element( 'model/endo/t' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, 1, '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, 4, 'conc (mM)' ) + plt.show() + + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/testXreacs8.py b/moose-core/tests/python/testXreacs8.py new file mode 100644 index 0000000000000000000000000000000000000000..58dc5cf418b5e170628e89dfec83af672398efe2 --- /dev/null +++ b/moose-core/tests/python/testXreacs8.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here we set up equal Kf and Kb in a reversible reaction across a +## 1-voxel cyl compt and an internal endoMesh, having a smaller volume. +## \ +## COMPT: 2 s <===> / 2 s :ENDO +## \ +## +## This becomes: +## \ +## COMPT: 2 s <===> 2 s_xfer_endo / 2s :ENDO +## \ +## +######################################################################### + + +import math +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + rXfer.Kf = 0.01 # 0.01/sec + rXfer.Kb = 0.01 # 0.01/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def doPlot( ax, i, label ): + plot1 = '/model/plot' + str(i) + plot2 = '/model/plot' + str(i+1) + plot3 = '/model/plot' + str(i+2) + plt.ylabel( label ) + plt.xlabel( 'time(s)' ) + v1 = moose.element(plot1).vector + v2 = moose.element(plot2).vector + v3 = moose.element(plot3).vector + ax.plot( v1, label='s' ) + ax.plot( v2, 'x',label='es' ) + ax.plot( v3, label='xfer' ) + ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) + plt.legend() + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + if standalone: + fig = plt.figure( figsize=(12,10) ) + ax1 = fig.add_subplot(211) + doPlot( ax1, 1, '# of molecules' ) + ax2 = fig.add_subplot(212) + doPlot( ax2, 4, 'conc (mM)' ) + plt.show() + moose.delete( '/model' ) + + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_GraupnerBrunel2012_STDPfromCaPlasticity.py b/moose-core/tests/python/test_GraupnerBrunel2012_STDPfromCaPlasticity.py new file mode 100644 index 0000000000000000000000000000000000000000..73aa8c9e50367b711761d7c0aa4b08d8569195df --- /dev/null +++ b/moose-core/tests/python/test_GraupnerBrunel2012_STDPfromCaPlasticity.py @@ -0,0 +1,228 @@ +# -*- coding: utf-8 -*- +# This script is modified version of GraupnerBrunel2012 model by Aditya Gilra. +# Modification is following: +# - Added global seed. +# - Removed some messages. +# - Added assertion. +# +# NOTE: This script is used for testing random number generators on various +# platform. This should not be used in any tutorial or scientific demo. + +import matplotlib as mpl +mpl.use('Agg') +import moose +print( 'Using moose from %s' % moose.__file__ ) +import numpy as np + +moose.seed( 10 ) + +def main(): + """ + Simulate a pseudo-STDP protocol and plot the STDP kernel + that emerges from Ca plasticity of Graupner and Brunel 2012. + + Author: Aditya Gilra, NCBS, Bangalore, October, 2014. + """ + + # ########################################### + # Neuron models + # ########################################### + + ## Leaky integrate and fire neuron + Vrest = -65e-3 # V # resting potential + Vt_base = -45e-3 # V # threshold + Vreset = -55e-3 # V # in current steps, Vreset is same as pedestal + R = 1e8 # Ohm + tau = 10e-3 # s + refrT = 2e-3 # s + + # ########################################### + # Initialize neuron group + # ########################################### + + ## two neurons: index 0 will be presynaptic, 1 will be postsynaptic + network = moose.LIF( 'network', 2 ); + moose.le( '/network' ) + network.vec.Em = Vrest + network.vec.thresh = Vt_base + network.vec.refractoryPeriod = refrT + network.vec.Rm = R + network.vec.vReset = Vreset + network.vec.Cm = tau/R + network.vec.inject = 0. + network.vec.initVm = Vrest + + tauCa = 20e-3 + tauSyn = 150.0 + CaPre = 1.0 + CaPost = 2.0 + delayD = 13.7e-3 + thetaD = 1.0 + thetaP = 1.3 + gammaD = 200.0 + gammaP = 321.808 + J = 5e-3 # V + weight = 0.5 + bistable = True + + syn = moose.GraupnerBrunel2012CaPlasticitySynHandler( '/network/syn' ) + syn.numSynapses = 1 + moose.connect( syn, 'activationOut', network.vec[1], 'activation' ) + + # synapse from presynaptic neuron + moose.connect( network.vec[0],'spikeOut', syn.synapse[0], 'addSpike') + + # post-synaptic spikes also needed for STDP + moose.connect( network.vec[1], 'spikeOut', syn, 'addPostSpike') + + syn.synapse[0].delay = 0.0 + syn.synapse[0].weight = weight + syn.CaInit = 0.0 + syn.tauCa = tauCa + syn.tauSyn = tauSyn + syn.CaPre = CaPre + syn.CaPost = CaPost + syn.delayD = delayD + syn.thetaD = thetaD + syn.thetaP = thetaP + syn.gammaD = gammaD + syn.gammaP = gammaP + syn.weightScale = J + syn.weightMax = 1.0 + syn.weightMin = 0. + + syn.noisy = True + syn.noiseSD = 1.3333 + syn.bistable = bistable + + # ########################################### + # Setting up tables + # ########################################### + + Vms = moose.Table( '/plotVms', 2 ) + moose.connect( network, 'VmOut', Vms, 'input', 'OneToOne') + spikes = moose.Table( '/plotSpikes', 2 ) + moose.connect( network, 'spikeOut', spikes, 'input', 'OneToOne') + CaTable = moose.Table( '/plotCa', 1 ) + moose.connect( CaTable, 'requestOut', syn, 'getCa') + WtTable = moose.Table( '/plotWeight', 1 ) + moose.connect( WtTable, 'requestOut', syn.synapse[0], 'getWeight') + + dt = 1e-3 + moose.useClock( 0, '/network/syn', 'process' ) + moose.useClock( 1, '/network', 'process' ) + moose.useClock( 2, '/plotSpikes', 'process' ) + moose.useClock( 3, '/plotVms', 'process' ) + moose.useClock( 3, '/plotCa', 'process' ) + moose.useClock( 3, '/plotWeight', 'process' ) + moose.setClock( 0, dt ) + moose.setClock( 1, dt ) + moose.setClock( 2, dt ) + moose.setClock( 3, dt ) + moose.setClock( 9, dt ) + moose.reinit() + + # function to make the aPlus and aMinus settle to equilibrium values + settletime = 10e-3 # s + def reset_settle(): + """ Call this between every pre-post pair + to reset the neurons and make them settle to rest. + """ + syn.synapse[0].weight = weight + syn.Ca = 0.0 + moose.start(settletime) + # Ca gets a jump at pre-spike+delayD + # So this event can occur during settletime + # So set Ca and weight once more after settletime + syn.synapse[0].weight = weight + syn.Ca = 0.0 + + # function to inject a sharp current pulse to make neuron spike + # immediately at a given time step + def make_neuron_spike(nrnidx,I=1e-7,duration=1e-3): + """ Inject a brief current pulse to + make a neuron spike + """ + network.vec[nrnidx].inject = I + moose.start(duration) + network.vec[nrnidx].inject = 0. + + dwlist_neg = [] + ddt = 10e-3 # s + # since CaPlasticitySynHandler is event based + # multiple pairs are needed for Ca to be registered above threshold + # Values from Fig 2, last line of legend + numpairs = 60 # number of spike parts per deltat + t_between_pairs = 1.0 # time between each spike pair + t_extent = 100e-3 # s # STDP kernel extent, + # t_extent > t_between_pairs/2 inverts pre-post pairing! + # dt = tpost - tpre + # negative dt corresponds to post before pre + print('-----------------------------------------------') + for deltat in np.arange(t_extent,0.0,-ddt): + reset_settle() + for i in range(numpairs): + # post neuron spike + make_neuron_spike(1) + moose.start(deltat) + # pre neuron spike after deltat + make_neuron_spike(0) + moose.start(t_between_pairs) # weight changes after pre-spike+delayD + # must run for at least delayD after pre-spike + dw = ( syn.synapse[0].weight - weight ) / weight + print(('post before pre, dt = %1.3f s, dw/w = %1.3f'%(-deltat,dw))) + dwlist_neg.append(dw) + + print('-----------------------------------------------') + # positive dt corresponds to pre before post + dwlist_pos = [] + for deltat in np.arange(ddt,t_extent+ddt,ddt): + reset_settle() + for i in range(numpairs): + # pre neuron spike + make_neuron_spike(0) + moose.start(deltat) + # post neuron spike after deltat + make_neuron_spike(1) + moose.start(t_between_pairs) + dw = ( syn.synapse[0].weight - weight ) / weight + print(('pre before post, dt = %1.3f s, dw/w = %1.3f'%(deltat,dw))) + dwlist_pos.append(dw) + + Vmseries0 = Vms.vec[0].vector + numsteps = len(Vmseries0) + + for t in spikes.vec[0].vector: + Vmseries0[int(t/dt)-1] = 30e-3 # V + + Vmseries1 = Vms.vec[1].vector + + for t in spikes.vec[1].vector: + Vmseries1[int(t/dt)-1] = 30e-3 # V + + timeseries = np.linspace(0.,200*numsteps*dt,numsteps) + + # STDP curve + up, sp = np.mean( dwlist_pos ), np.std( dwlist_pos ) + un, sn = np.mean( dwlist_neg ), np.std( dwlist_neg ) + + expected = [0.32476025611655324, 0.22658173497286094, + 0.02706212384326734, -0.2176119329016457, -0.17349820098625146, + -0.049000627347906, 0.10942145078777199, 0.015381955378225953, + 0.004742824127517586, -0.12298343312253879] + assert np.isclose(dwlist_pos[1:], expected[1:]).all(), "Got %s \nexpected %s" % (dwlist_pos, expected) + + expected = [-0.07871282492831622, 0.11915009122888964, + -0.028510348966579557, 0.11812233585111875, 0.05098143255634335, + -0.2303047508248669, 0.18033418630802123, -0.019377885225611347, + -0.06038610826728241, 0.06575882890278106] + assert np.isclose(dwlist_neg[1:], expected[1:]).all(), "Got %s\nexpected %s" % (dwlist_neg, + expected) + + + got = (up, sp) + expNew = (0.014485615086785508, 0.16206703949072981) + assert np.isclose(got, expNew).all(), 'Expected: %s, Got: %s' % (str(expNew), str(got)) + +if __name__ == '__main__': + main() diff --git a/moose-core/tests/python/test_Xchan1.py b/moose-core/tests/python/test_Xchan1.py new file mode 100644 index 0000000000000000000000000000000000000000..35fc56f647a36ebebe6c33841eca6c9371bbd4cb --- /dev/null +++ b/moose-core/tests/python/test_Xchan1.py @@ -0,0 +1,153 @@ +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here test ConcChan. We set up a channel and a pump and run two tests. +## First we have zero flux through the pump and check that the conc +## equalizes on both sides of the membrane. Then we change the Kf of +## the pump to a value designed to give twice the conc In as Out. +## The system is a 1-voxel cyl compt and an internal endoMesh, having a +## volume = 1/8 of the cylinder. +## \ +## COMPT: s ----> / s :ENDO +## s =chan= s +## \ +## +## This becomes: +## \ +## COMPT: s ----> s_xfer_endo / s :ENDO +## s =chan= s +## \ +## +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + # Note that the chanPool must be on the 'In' compartment. + #chanPool = moose.Pool( '/model/compartment/chanPool' ) + #chan = moose.ConcChan( '/model/compartment/chanPool/chan' ) + chanPool = moose.Pool( '/model/endo/chanPool' ) + chan = moose.ConcChan( '/model/endo/chanPool/chan' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + moose.connect( chanPool, 'nOut', chan, 'setNumChan' ) + moose.connect( chan, 'out', s, 'reac' ) + moose.connect( chan, 'in', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.0 # 0.02/sec + rXfer.Kb = 0.0 # + s.concInit = 0.001 + chanPool.nInit = 1000.0 + # Flux (mM/s) = permeability * N * (conc_out - conc_in ) + chan.permeability = 0.1 * chanPool.volume * 6.022e23 / chanPool.nInit + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + displayInterval = 2 + makeModel() + for i in range( 10, 18 ): + moose.setClock( i, 0.01 ) + moose.reinit() + moose.start( runtime ) + s = moose.element( '/model/compartment/s' ) + es = moose.element( '/model/endo/s' ) + assert( almostEq( s.conc, es.conc ) ) + # We go for concEndo = 2x concOut. Then + # We already know volIn = volOut/8 + # #in/volIn = 2x #out/volOut + # #in/volIn = 2x #out/(8*volIn) + # so #in = #out/4 + # From consv, #in + #out = nInit + # so 5/4#out = nInit => + # #out = 0.8*nInit; #in = 0.2*nInit + # + # flux = perm * nChan * (0.8nInit/volOut - 0.2nInit/(volOut/8) ) = + # perm * (nChan*nInit/volOut) * (0.8 - 0.2*8) = + # perm * (nChan*nInit/volOut) * (-0.8) + # + # This has to be balanced by flux = numKf * nOut = numKf * 0.8 * nInit + # So 0.8*numKf*nInit = 0.8*perm*nChan*nInit/volOut + + # Note that chan.permeability = 0.1*chanPool.volume / chanPool.nInit + + # so numKf = perm*nChan/volOut = (0.1*volIn/nChan)*nChan/volOut=0.1/8 + # + rXfer = moose.element( '/model/compartment/rXfer' ) + rXfer.numKf = 0.1/8.0 + moose.start( runtime ) + assert( almostEq( 2 * s.conc, es.conc ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xdiff1.py b/moose-core/tests/python/test_Xdiff1.py new file mode 100644 index 0000000000000000000000000000000000000000..fc9df5d8879755578e9e69588681731a470408e4 --- /dev/null +++ b/moose-core/tests/python/test_Xdiff1.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here test diffusion across a junction. We set up a pump and change its +## rate to do a check on the calculation of the diffusion rate separate +## from the verification that diffusion gives equal concs on either side. +## The system is a ## 1-voxel cyl compt and an internal endoMesh, +## having a volume = 1/8 of the parent cylinder.. +## \ +## COMPT: s ----> / s :ENDO +## s =diffn= s +## \ +## +## This becomes: +## \ +## COMPT: s ----> s_xfer_endo / s :ENDO +# s =diffn= s +## \ +## +######################################################################### + + +import math +import numpy as np +import moose +print( '[INFO] Using moose from %s, %s' % (moose.__file__, moose.version()) ) +import fixXreacs + +diffConst = 1e-16 + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = False + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + #print( "Volume ratio = {}".format( volRatio ) ) + rXfer.Kf = 0.0 # 0.02/sec + rXfer.Kb = 0.0 # + s.concInit = 0.001 + s.diffConst = diffConst + es.diffConst = diffConst + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def almostEq( a, b ): + # print( a, b, (a-b)/(a+b) ) + return abs(a-b)/(a+b) < 6e-5 + +def main( standalone = False ): + runtime = 100 + makeModel() + for i in range( 10, 18 ): + moose.setClock( i, 0.01 ) + moose.reinit() + moose.start( runtime, 1 ) + s = moose.element( '/model/compartment/s' ) + es = moose.element( '/model/endo/s' ) + assert( almostEq( s.conc, es.conc ) ) + rXfer = moose.element( '/model/compartment/rXfer' ) + endo = moose.element( '/model/endo' ) + compt = moose.element( '/model/compartment' ) + endoA = endo.aScale * pow( compt.volume, endo.aPower ) + rXfer.numKf = 2.0*diffConst*endoA/(compt.r0*compt.volume) + moose.start( runtime ) + assert almostEq( 2 * s.conc, es.conc ), "%g=?%g" % (2*s.conc, es.conc) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xenz1.py b/moose-core/tests/python/test_Xenz1.py new file mode 100644 index 0000000000000000000000000000000000000000..c7463ad47aa9f6d77484af09bdd7f46fbea5fd29 --- /dev/null +++ b/moose-core/tests/python/test_Xenz1.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## +## Endo / Compartment +## \ +## sub--enz-/-----> prd +## sub<-----\----- prd +## / +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +subInit = 0.002 +eInit = 0.001 +Km = 0.001 +kcat = 0.2 +Kf = 0.1 + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + prd = moose.Pool( '/model/compartment/prd' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + sub = moose.Pool( '/model/endo/sub' ) + enzPool = moose.Pool( '/model/endo/enzPool' ) + enzPool.concInit = eInit + enz = moose.MMenz( '/model/endo/enzPool/enz' ) + ##################################################################### + moose.connect( enz, 'sub', sub, 'reac' ) + moose.connect( enz, 'prd', prd, 'reac' ) + moose.connect( enzPool, 'nOut', enz, 'enzDest' ) + moose.connect( rXfer, 'sub', prd, 'reac' ) + moose.connect( rXfer, 'prd', sub, 'reac' ) + rXfer.Kf = Kf # 0.04/sec + rXfer.Kb = 0.0 # 0.02/sec + enz.Km = Km + enz.kcat = kcat + # v = es.kcat/(s+Km) + # v = Kf * conc. + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + sub.vec.concInit = subInit + enzPool.vec.concInit = eInit + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 3 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', sub, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', prd, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', sub, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', prd, 'getConc' ) + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + for i in range( 10, 18 ): + moose.setClock( i, 0.001 ) + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/prd' ).n, + moose.element( '/model/endo/sub' ).n ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs2.py b/moose-core/tests/python/test_Xreacs2.py new file mode 100644 index 0000000000000000000000000000000000000000..1b1e73026b1c48c5049ac2bd54187c5d423ab1ee --- /dev/null +++ b/moose-core/tests/python/test_Xreacs2.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +import os +import sys +import moose +import numpy as np +import fixXreacs + +def countCrossings( plot, thresh ): + vec = moose.element( plot ).vector + #print (vec[:-1] < thresh) + return sum( (vec[:-1] < thresh) * (vec[1:] >= thresh ) ) + +def main( standalone = False ): + mfile = os.path.join( os.path.dirname( __file__), 'OSC_diff_vols.g' ) + runtime = 4000.0 + modelId = moose.loadModel( mfile, 'model', 'ee' ) + kin = moose.element( '/model/kinetics' ) + compt1 = moose.element( '/model/compartment_1' ) + compt1.x1 += kin.x1 + compt1.x0 += kin.x1 + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + + ks1 = moose.Ksolve( '/model/kinetics/ksolve' ) + ds1 = moose.Dsolve( '/model/kinetics/dsolve' ) + s1 = moose.Stoich( '/model/kinetics/stoich' ) + s1.compartment = moose.element( '/model/kinetics' ) + s1.ksolve = ks1 + s1.dsolve = ds1 + s1.path = '/model/kinetics/##' + + ks2 = moose.Ksolve( '/model/compartment_1/ksolve' ) + ds2 = moose.Dsolve( '/model/compartment_1/dsolve' ) + s2 = moose.Stoich( '/model/compartment_1/stoich' ) + s2.compartment = moose.element( '/model/compartment_1' ) + s2.ksolve = ks2 + s2.dsolve = ds2 + s2.path = '/model/compartment_1/##' + + ds2.buildMeshJunctions( ds1 ) + + moose.reinit() + moose.start( runtime ) + # I don't have an analytic way to assess oscillations + assert( countCrossings( '/model/graphs/conc2/M.Co', 0.001 ) == 4 ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs3.py b/moose-core/tests/python/test_Xreacs3.py new file mode 100644 index 0000000000000000000000000000000000000000..53cd7600b05a55a31d60321fed6891baf3b9e3bf --- /dev/null +++ b/moose-core/tests/python/test_Xreacs3.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here we set up equal Kf and Kb in a reversible reaction across a +## 1-voxel cyl compt and an internal endoMesh, having a smaller volume. +## \ +## COMPT: s <===> / s :ENDO +## \ +## +## This becomes: +## \ +## COMPT: s <===> s_xfer_endo / s :ENDO +## \ +## +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.02 # 0.01/sec + rXfer.Kb = 0.02 # 1/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs4.py b/moose-core/tests/python/test_Xreacs4.py new file mode 100644 index 0000000000000000000000000000000000000000..c655e4e5fe9727ed9e055887c006768924e27e47 --- /dev/null +++ b/moose-core/tests/python/test_Xreacs4.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.02 # 0.02/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs4a.py b/moose-core/tests/python/test_Xreacs4a.py new file mode 100644 index 0000000000000000000000000000000000000000..73c6d54746c88d36238904116547f73969eed6b5 --- /dev/null +++ b/moose-core/tests/python/test_Xreacs4a.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + rXfer = moose.Reac( '/model/endo/rXfer' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + volRatio = compartment.volume / endo.volume + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.02 # 0.02/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 1 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 200 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + moose.delete( '/model' ) + + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs5.py b/moose-core/tests/python/test_Xreacs5.py new file mode 100644 index 0000000000000000000000000000000000000000..4dde2a47f1b673fbe9065d0f81fff2493e08a195 --- /dev/null +++ b/moose-core/tests/python/test_Xreacs5.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + erXfer = moose.Reac( '/model/endo/erXfer' ) + ##################################################################### + moose.connect( erXfer, 'sub', es, 'reac' ) + moose.connect( erXfer, 'prd', s, 'reac' ) + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.0 # 0.00/sec + erXfer.Kf = 0.16 # 0.16/sec + erXfer.Kb = 0.0 # 0.00/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + for i in range( 10, 18): + moose.setClock( i, 0.001 ) + runtime = 100 + makeModel() + moose.reinit() + moose.start( runtime ) + + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs5a.py b/moose-core/tests/python/test_Xreacs5a.py new file mode 100644 index 0000000000000000000000000000000000000000..126f918238b6019a65ca0f4052aadb8f1b258be3 --- /dev/null +++ b/moose-core/tests/python/test_Xreacs5a.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + erXfer = moose.Reac( '/model/compartment/erXfer' ) + ##################################################################### + moose.connect( erXfer, 'sub', es, 'reac' ) + moose.connect( erXfer, 'prd', s, 'reac' ) + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + rXfer.Kf = 0.04 # 0.04/sec + rXfer.Kb = 0.0 # 0.02/sec + erXfer.Kf = 0.02 # 0.04/sec + erXfer.Kb = 0.0 # 0.02/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + rx = moose.element( '/model/compartment/rXfer' ) + erx = moose.element( '/model/compartment/erXfer' ) + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 200 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).n, + moose.element( '/model/endo/s' ).n ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs6.py b/moose-core/tests/python/test_Xreacs6.py new file mode 100644 index 0000000000000000000000000000000000000000..35f21c5be50c28cc7593795b9a0645020c9ff1ed --- /dev/null +++ b/moose-core/tests/python/test_Xreacs6.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2018 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU General Public License version 3 or later. +## See the file COPYING.LIB for the full notice. +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + t = moose.Pool( '/model/compartment/t' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + et = moose.Pool( '/model/endo/t' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'sub', t, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + moose.connect( rXfer, 'prd', et, 'reac' ) + rXfer.Kf = 0.02 # 0.02/mM/sec + rXfer.Kb = 0.02 # 0.02/mM/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 4 ) + s.vec.concInit = [1]*num + t.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 2 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + plot3 = moose.Table2( '/model/plot3' ) + plot4 = moose.Table2( '/model/plot4' ) + moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + for i in range( 10, 18): + moose.setClock( i, 0.01 ) + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs7.py b/moose-core/tests/python/test_Xreacs7.py new file mode 100644 index 0000000000000000000000000000000000000000..913a7a1cc791ac674967bc9360f5f5cdd083afe7 --- /dev/null +++ b/moose-core/tests/python/test_Xreacs7.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2018 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU General Public License version 3 or later. +## See the file COPYING.LIB for the full notice. +## +## This file makes u + t <=====> s where u is in a different compt from t,s +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + u = moose.Pool( '/model/compartment/u' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + rXfer = moose.Reac( '/model/endo/rXfer' ) + et = moose.Pool( '/model/endo/t' ) + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', u, 'reac' ) + moose.connect( rXfer, 'sub', et, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + u.concInit = 1.0 + et.concInit = 1.0 + + ##################################################################### + # [u0] = 1 in compt, [t0] = 1 in endo, [s0] = 0 + # [u] + [s]/8 = [u0] ; [t] + [s] = [t0]; nu + ns = nu0, nt + ns = nt0 + # At equil, numKf*nu*nt = numKb*ns + # Express all # in terms of ns. + # nu = nu0-ns; nt = nt0-ns Also, nu0 = 8*nt0 + # So numKf*(nu0-ns)*(nt0-ns) = numKb*ns + # Target level is nt = ns = nt0/2 + # So numKf*( 8nt0 - nt0/2)*nt0/2 = numKb*nt0/2 + # So 7.5*nt0 = numKb/numKf + rXfer.numKb = 0.1 + rXfer.numKf = 0.1/(7.5 * et.nInit) + #print( "Rates = {}, {}".format( rXfer.Kf, rXfer.Kb )) + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + #fixXreacs.restoreXreacs( '/model' ) + #fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/compartment/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 1 ) + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 3 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', u, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', et, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', es, 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', u, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', et, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', es, 'getConc' ) + +def almostEq( a, b ): + #print a, b, (a-b)/(a+b) + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + displayInterval = 2 + makeModel() + moose.reinit() + moose.start( runtime ) + + assert( almostEq( moose.element( 'model/endo/t' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + moose.delete( '/model' ) + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_Xreacs8.py b/moose-core/tests/python/test_Xreacs8.py new file mode 100644 index 0000000000000000000000000000000000000000..15bb0f01a4a95687085d7eb3f39729d4207b3b3a --- /dev/null +++ b/moose-core/tests/python/test_Xreacs8.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +## Here we set up equal Kf and Kb in a reversible reaction across a +## 1-voxel cyl compt and an internal endoMesh, having a smaller volume. +## \ +## COMPT: 2 s <===> / 2 s :ENDO +## \ +## +## This becomes: +## \ +## COMPT: 2 s <===> 2 s_xfer_endo / 2s :ENDO +## \ +## +######################################################################### + + +import math +import numpy as np +import moose +import fixXreacs + +def makeModel(): + # create container for model + num = 1 # number of compartments + model = moose.Neutral( '/model' ) + compartment = moose.CylMesh( '/model/compartment' ) + compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder + + # create molecules and reactions + s = moose.Pool( '/model/compartment/s' ) + rXfer = moose.Reac( '/model/compartment/rXfer' ) + ##################################################################### + # Put in endo compartment. Add molecule s + endo = moose.EndoMesh( '/model/endo' ) + endo.isMembraneBound = True + endo.surround = compartment + es = moose.Pool( '/model/endo/s' ) + ##################################################################### + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'sub', s, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + moose.connect( rXfer, 'prd', es, 'reac' ) + rXfer.Kf = 0.01 # 0.01/sec + rXfer.Kb = 0.01 # 0.01/sec + + ##################################################################### + fixXreacs.fixXreacs( '/model' ) + fixXreacs.restoreXreacs( '/model' ) + fixXreacs.fixXreacs( '/model' ) + ##################################################################### + + # Make solvers + ksolve = moose.Ksolve( '/model/compartment/ksolve' ) + dsolve = moose.Dsolve( '/model/dsolve' ) + eksolve = moose.Ksolve( '/model/endo/ksolve' ) + edsolve = moose.Dsolve( '/model/endo/dsolve' ) + + stoich = moose.Stoich( '/model/compartment/stoich' ) + stoich.compartment = compartment + stoich.ksolve = ksolve + stoich.dsolve = dsolve + stoich.path = "/model/compartment/##" + assert( dsolve.numPools == 2 ) + s.vec.concInit = [1]*num + + estoich = moose.Stoich( '/model/endo/stoich' ) + estoich.compartment = endo + estoich.ksolve = eksolve + estoich.dsolve = edsolve + estoich.path = "/model/endo/##" + assert( edsolve.numPools == 1 ) + + edsolve.buildMeshJunctions( dsolve ) + + plot1 = moose.Table2( '/model/plot1' ) + plot2 = moose.Table2( '/model/plot2' ) + plot3 = moose.Table2( '/model/plot3' ) + moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) + moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) + moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) + plot4 = moose.Table2( '/model/plot4' ) + plot5 = moose.Table2( '/model/plot5' ) + plot6 = moose.Table2( '/model/plot6' ) + moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) + moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) + moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) + +def almostEq( a, b ): + return abs(a-b)/(a+b) < 5e-5 + +def main( standalone = False ): + runtime = 100 + makeModel() + moose.reinit() + moose.start( runtime ) + assert( almostEq( moose.element( 'model/compartment/s' ).conc, + moose.element( '/model/endo/s' ).conc ) ) + moose.delete( '/model' ) + + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main( standalone = True ) diff --git a/moose-core/tests/python/test_connectionLists.py b/moose-core/tests/python/test_connectionLists.py index 057cd5a47749d474f6fb05e1c2e2d987f6b69367..fcd7786725615960e1d93b02834c3b9b189af151 100644 --- a/moose-core/tests/python/test_connectionLists.py +++ b/moose-core/tests/python/test_connectionLists.py @@ -66,8 +66,14 @@ def makeGlobalBalanceNetwork(): inhibMatrix.setRandomConnectivity( params['stimToInhProb'], params['stimToInhSeed'] ) cl = inhibMatrix.connectionList - expectedCl = [ 1,4,13,13,26,42,52,56,80,82,95,97,4,9,0,9,4,8,0,6,1,6,6,7] - assert list(cl) == expectedCl, "Expected %s, got %s" % (expectedCl, cl ) + + # This can change when random-number generator changes. + # This was before we used c++11 <random> to generate random numbers. This + # test has changes on Tuesday 31 July 2018 11:12:35 AM IST + # expectedCl = [ 1,4,13,13,26,42,52,56,80,82,95,97,4,9,0,9,4,8,0,6,1,6,6,7] + expectedCl=[0,6,47,50,56,67,98,2,0,3,5,4,8,3] + + assert list(cl) == expectedCl, "Expected %s, got %s" % (expectedCl, cl) temp = moose.connect( stim, 'spikeOut', ov, 'addSpike', 'Sparse' ) excMatrix = moose.element( temp ) @@ -80,7 +86,9 @@ def makeGlobalBalanceNetwork(): params['inhToOutProb'], params['inhToOutSeed'] ) # print("ConnMtxEntries: ", inhibMatrix.numEntries, excMatrix.numEntries, negFFMatrix.numEntries) - assert (12, 57, 48) == (inhibMatrix.numEntries, excMatrix.numEntries, negFFMatrix.numEntries) + got = (inhibMatrix.numEntries, excMatrix.numEntries, negFFMatrix.numEntries) + expected = (7, 62, 55) + assert expected == got, "Expected %s, Got %s" % (expected,got) cl = negFFMatrix.connectionList numInhSyns = [ ] @@ -93,7 +101,9 @@ def makeGlobalBalanceNetwork(): if i.synapse.num > 0: i.synapse.weight = params['wtStimToInh'] - assert numInhSyns == [2,1,0,0,2,0,3,1,1,2] + # expected = [2,1,0,0,2,0,3,1,1,2] + expected = [1, 0, 1, 2, 1, 1, 0, 0, 1, 0] + assert numInhSyns == expected, "Expected %s, got %s" % (expected,numInhSyns) for i in moose.vec( outsyn ): nov += i.synapse.num @@ -105,12 +115,12 @@ def makeGlobalBalanceNetwork(): if i.synapse.num > 0: i.synapse.weight = params['wtInhToOut'] - # print("SUMS: ", sum( iv.numField ), sum( ov.numField ), sum( oiv.numField )) - assert [4,49,9] == [sum( iv.numField ), sum( ov.numField ), sum( oiv.numField )] - # print("SUMS2: ", niv, nov, noiv) - assert [12,57,48] == [ niv, nov, noiv ] - # print("SUMS3: ", sum( insyn.vec.numSynapses ), sum( outsyn.vec.numSynapses ), sum( outInhSyn.vec.numSynapses )) - assert [12, 57, 48 ] == [ sum( insyn.vec.numSynapses ), sum( outsyn.vec.numSynapses ), sum( outInhSyn.vec.numSynapses ) ] + print("SUMS: ", sum( iv.numField ), sum( ov.numField ), sum( oiv.numField )) + assert [1, 64, 25] == [sum( iv.numField ), sum( ov.numField ), sum( oiv.numField )] + print("SUMS2: ", niv, nov, noiv) + assert [7, 62, 55] == [ niv, nov, noiv ] + print("SUMS3: ", sum( insyn.vec.numSynapses ), sum( outsyn.vec.numSynapses ), sum( outInhSyn.vec.numSynapses )) + assert [7,62,55] == [ sum( insyn.vec.numSynapses ), sum( outsyn.vec.numSynapses ), sum( outInhSyn.vec.numSynapses ) ] # print(oiv.numField) # print(insyn.vec[1].synapse.num) diff --git a/moose-core/tests/python/test_difshells.py b/moose-core/tests/python/test_difshells.py index 4ba00d8a59d15fc53de39e4bd3b07c34b0eff0d8..d9e29fe5d032b8a876a8cb0beeb2850e6b8bb0ab 100644 --- a/moose-core/tests/python/test_difshells.py +++ b/moose-core/tests/python/test_difshells.py @@ -1,10 +1,36 @@ # -*- coding: utf-8 -*- import moose +print( 'Using moose from %s. VERSION=%s' % (moose.__file__, moose.__version__) ) import numpy as np import chan_proto import param_chan -from params import * +t_stop = 10 +dend_diameter = 2.2627398e-6 +dend_length = 1.131369936e-6 +Cm = 4.021231698e-12 +Rm = 1865100032 +Em = -0.07100000232 +Vm_0 = -0.0705 +dt = 50e-6 +spines_no = 0 +difshell_no = 2 +difshell_name = "Ca_shell" +Ca_basal = 50e-6 +Ca_initial = Ca_basal*200 +dca = 200.0e-12 +difbuff_no = 1 +difbuff_name = "Buff" +btotal = 80.0e-3 +kf = 0.028e6 +kb = 19.6 +d = 66e-12 +inject = 0.1e-9 +gbar = 1 +#MMpump +km = 0.3e-3 +kcat = 85e-22 +pumps = 1 def linoid(x, param): den = (param[2] + np.exp((V + param[3]) / param[4])) @@ -93,7 +119,6 @@ def addOneChan(chanpath, gbar,comp): moose.connect(chan, "channelOut", comp, "handleChannel") return chan - if __name__ == '__main__': lib = moose.Neutral('/library') for tick in range(0, 7): diff --git a/moose-core/tests/python/test_kkit.py b/moose-core/tests/python/test_kkit.py index ba194d63c44f58abb5f0c1d8a3235bed5f42f92e..0b7c37583ace6fbd5c61d8425dad5e69314a8f43 100644 --- a/moose-core/tests/python/test_kkit.py +++ b/moose-core/tests/python/test_kkit.py @@ -24,7 +24,7 @@ def main(): if ( len( sys.argv ) == 4 ): solver = sys.argv[3] modelId = moose.loadModel( mfile, 'model') - moose.mooseaddChemSolver('model',solver) + moose.mooseAddChemSolver('model',solver) # Increase volume so that the stochastic solver gssa # gives an interesting output diff --git a/moose-core/tests/python/test_muparser.py b/moose-core/tests/python/test_muparser.py index 7adf0e26757604cb78cb53983cd5399fce2fa7a0..d5f92311f14fd73c03cca91bfcb256fb27ad7bd6 100644 --- a/moose-core/tests/python/test_muparser.py +++ b/moose-core/tests/python/test_muparser.py @@ -8,6 +8,8 @@ Modified from https://elifesciences.org/articles/25827 , Fig4.py import sys import os import numpy as np +import matplotlib as mpl +mpl.use('Agg') import sys import numpy as np import moose diff --git a/moose-core/tests/python/test_negative_value_flag.py b/moose-core/tests/python/test_negative_value_flag.py index 7b073975de42881f5abab9f8cb4f40c6f029e12f..70861540478ea85c89b2626ce5aebc41b2954abf 100644 --- a/moose-core/tests/python/test_negative_value_flag.py +++ b/moose-core/tests/python/test_negative_value_flag.py @@ -36,7 +36,7 @@ def main(): solver = sys.argv[3] modelId = moose.loadModel( mfile, 'model') - moose.mooseaddChemSolver('model',solver) + moose.mooseAddChemSolver('model',solver) moose.element( '/model/kinetics/neuroNOS/nNOS.arg' ).concInit = 0.1 moose.reinit() moose.start( runtime ) diff --git a/moose-core/tests/python/test_neuroml2.py b/moose-core/tests/python/test_neuroml2.py index 5155515d12e139bef053aaba01f3b9b2c219b387..8460c092195f22de18a256cc7371045a8e0a192c 100644 --- a/moose-core/tests/python/test_neuroml2.py +++ b/moose-core/tests/python/test_neuroml2.py @@ -1,43 +1,7 @@ # -*- coding: utf-8 -*- # test_neurom2.py, modified from run_cell.py -# Description: -# Author: # Maintainer: P Gleeson, Dilawar Singh -# Version: -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - +# This test is not robust. # Code: from __future__ import absolute_import, print_function, division @@ -49,7 +13,7 @@ import os import numpy as np SCRIPT_DIR = os.path.dirname( os.path.realpath( __file__ ) ) - + def run( nogui = True ): global SCRIPT_DIR filename = os.path.join(SCRIPT_DIR, 'test_files/passiveCell.nml' ) @@ -57,26 +21,25 @@ def run( nogui = True ): nml = moose.mooseReadNML2( filename ) if not nml: mu.warn( "Failed to parse NML2 file" ) - return + return assert nml, "Expecting NML2 object" msoma = nml.getComp(nml.doc.networks[0].populations[0].id,0,0) data = moose.Neutral('/data') pg = nml.getInput('pulseGen1') - + inj = moose.Table('%s/pulse' % (data.path)) moose.connect(inj, 'requestOut', pg, 'getOutputValue') - - + vm = moose.Table('%s/Vm' % (data.path)) moose.connect(vm, 'requestOut', msoma, 'getVm') - + simtime = 150e-3 moose.reinit() moose.start(simtime) print("Finished simulation!") t = np.linspace(0, simtime, len(vm.vector)) - yvec = vm.vector + yvec = vm.vector injvec = inj.vector * 1e12 m1, u1 = np.mean( yvec ), np.std( yvec ) m2, u2 = np.mean( injvec ), np.std( injvec ) diff --git a/moose-core/tests/python/test_random_num.py b/moose-core/tests/python/test_random_num.py new file mode 100644 index 0000000000000000000000000000000000000000..9be47e932b72742ea5c357e5c74cea94e92141db --- /dev/null +++ b/moose-core/tests/python/test_random_num.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +"""test_random_num.py: + +""" + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2017-, Dilawar Singh" +__version__ = "1.0.0" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" +__status__ = "Development" + +import sys +import os +import numpy as np +import moose + +try: + reload +except NameError: + # Python 3 + from imp import reload + +def unequal(): + rand1, rand2 = [], [] + N = 10 + for i in range( N ): + x = moose.rand() + rand1.append( x ) + reload( moose ) + for i in range( N ): + x = moose.rand() + rand2.append( x ) + + assert not np.equal( rand1, rand2 ).all() + +def equal(): + rand1, rand2 = [], [] + N = 10 + moose.seed( 10 ) + for i in range( N ): + x = moose.rand() + rand1.append( x ) + + reload( moose ) + moose.seed( 10 ) + for i in range( N ): + x = moose.rand() + rand2.append( x ) + + assert np.equal( rand1, rand2 ).all() + +def main( ): + unequal() + equal() + +if __name__ == '__main__': + main() + diff --git a/moose-core/tests/python/test_rdesigneur.py b/moose-core/tests/python/test_rdesigneur.py index 2972a3c06f71ae4f1312fbdae1282e84fe136bae..f53ac93f15bf7d92dae83afb57b112eb2dbfa152 100644 --- a/moose-core/tests/python/test_rdesigneur.py +++ b/moose-core/tests/python/test_rdesigneur.py @@ -11,6 +11,8 @@ __status__ = "Development" import sys import os +import matplotlib as mpl +mpl.use('Agg') import numpy as np import moose import rdesigneur as rd diff --git a/moose-core/tests/python/test_utils.py b/moose-core/tests/python/test_utils.py deleted file mode 100644 index a57633b84eb83766bbe848312947c472b0b7ee5a..0000000000000000000000000000000000000000 --- a/moose-core/tests/python/test_utils.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -import moose -import moose.utils as mu - -def main( ): - print( dir( mu ) ) - mu.info( 'Hellow' ) - -if __name__ == '__main__': - main() diff --git a/moose-core/utility/Annotator.cpp b/moose-core/utility/Annotator.cpp index 184ab6b668df8c1dfd06ce405b2182a3fc6e63ea..8dca2186f3cce73ad9db840ba7661c6e04f608ac 100644 --- a/moose-core/utility/Annotator.cpp +++ b/moose-core/utility/Annotator.cpp @@ -118,7 +118,7 @@ static const Cinfo* annotatorCinfo = Annotator::initCinfo(); Annotator::Annotator() : x_( 0.0 ), y_( 0.0 ), z_( 0.0 ), notes_( "" ), color_( "white" ), textColor_( "black" ), - icon_( "sphere" ),solver_( "gsl"),runtime_(100.0),dirpath_(""),modeltype_("") + icon_( "sphere" ),solver_( "ee"),runtime_(100.0),dirpath_(""),modeltype_("") { ; } diff --git a/moose-core/utility/cnpy.cpp b/moose-core/utility/cnpy.cpp index 4acc65580e111f05df03dcbfb3518173df9cd61e..131df10ce2794a27e20e46964cefe6ea64285a95 100644 --- a/moose-core/utility/cnpy.cpp +++ b/moose-core/utility/cnpy.cpp @@ -85,7 +85,11 @@ bool is_valid_numpy_file( FILE* fp ) { assert( fp ); char buffer[__pre__size__]; - fread( buffer, sizeof(char), __pre__size__, fp ); + size_t nr = fread( buffer, sizeof(char), __pre__size__, fp ); + + if( 0 == nr ) + return false; + bool equal = true; // Check for equality for(size_t i = 0; i < __pre__size__; i++ ) diff --git a/moose-core/utility/matrix_util.cpp b/moose-core/utility/matrix_util.cpp index 7db63a81721337d3b87fbb71d083d066d53d47bd..fecb4a4b92bd71fc2e1e35aca87278eaf9330bab 100644 --- a/moose-core/utility/matrix_util.cpp +++ b/moose-core/utility/matrix_util.cpp @@ -17,7 +17,7 @@ * ===================================================================================== */ -#ifdef USE_BOOST +#ifdef USE_BOOST_ODE #include "matrix_util.h" @@ -119,4 +119,4 @@ unsigned int rankUsingBoost( ublas::matrix<value_type>& U ) return i + 1; } -#endif /* ----- not USE_BOOST ----- */ +#endif /* ----- not USE_BOOST_ODE ----- */ diff --git a/moose-core/utility/matrix_util.h b/moose-core/utility/matrix_util.h index 9b232abbc1f86cbba76ac8bd02afc68f2b04a0c6..092dd0c3b258972428c33dd67efea1a79a4f2454 100644 --- a/moose-core/utility/matrix_util.h +++ b/moose-core/utility/matrix_util.h @@ -19,7 +19,7 @@ #ifndef matrix_util_INC #define matrix_util_INC -#ifdef USE_BOOST +#ifdef USE_BOOST_ODE #include <boost/numeric/ublas/matrix.hpp> #include "boost/numeric/bindings/lapack/lapack.hpp" diff --git a/moose-core/utility/print_function.hpp b/moose-core/utility/print_function.hpp index 5a1863ad375e33db482ce20e3ad793281c801b30..d3a9e8882e1b367fa00ca04d8d7922e73158e20c 100644 --- a/moose-core/utility/print_function.hpp +++ b/moose-core/utility/print_function.hpp @@ -53,8 +53,22 @@ using namespace std; -namespace moose { +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Macros + */ +/* ----------------------------------------------------------------------------*/ +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#ifdef NDEBUG +#define MOOSE_DEBUG( a ) { \ + stringstream ss; ss << a; \ + cout << "DEBUG: " << __FILENAME__ << ":" << __LINE__ << "| " << ss.str(); \ + } +#else +#define MOOSE_DEBUG( a ) {} +#endif +namespace moose { /** * @brief Enumerate type for debug and log. @@ -134,6 +148,7 @@ namespace moose { return ss.str(); } + // Not print it when built for release. inline string debugPrint(string msg, string prefix = "DEBUG" , string color=T_RESET, unsigned debugLevel = 0 ) @@ -211,6 +226,15 @@ namespace moose { moose::__dump__(msg, moose::warning ); } + inline void showDebug( const string msg ) + { +#ifdef DISABLE_DEBUG + +#else + moose::__dump__(msg, moose::debug ); +#endif + } + inline void showError( string msg ) { moose::__dump__( msg, moose::error ); diff --git a/moose-core/utility/strutil.cpp b/moose-core/utility/strutil.cpp index 399d2d71ccf0b0babd2e810b03ec60e8c373e313..da5ee41f3516092a294567923297289fd92f8c5e 100644 --- a/moose-core/utility/strutil.cpp +++ b/moose-core/utility/strutil.cpp @@ -12,38 +12,39 @@ using namespace std; -namespace moose { +namespace moose +{ // Adapted from code available on oopweb.com -void tokenize( - const string& str, - const string& delimiters, - vector< string >& tokens ) +void tokenize( const string& str, const string& delimiters, vector< string >& tokens ) { - // Token boundaries - string::size_type begin = str.find_first_not_of( delimiters, 0 ); - string::size_type end = str.find_first_of( delimiters, begin ); - - while ( string::npos != begin || string::npos != end ) - { - // Found a token, add it to the vector. - tokens.push_back( str.substr( begin, end - begin ) ); - - // Update boundaries - begin = str.find_first_not_of( delimiters, end ); - end = str.find_first_of( delimiters, begin ); - } + // Token boundaries + string::size_type begin = str.find_first_not_of( delimiters, 0 ); + string::size_type end = str.find_first_of( delimiters, begin ); + + while ( string::npos != begin || string::npos != end ) + { + // Found a token, add it to the vector. + tokens.push_back( str.substr( begin, end - begin ) ); + + // Update boundaries + begin = str.find_first_not_of( delimiters, end ); + end = str.find_first_of( delimiters, begin ); + } } string& clean_type_name(string& arg) { - for (size_t pos = arg.find(' '); pos != string::npos; pos = arg.find(' ')){ + for (size_t pos = arg.find(' '); pos != string::npos; pos = arg.find(' ')) + { arg.replace(pos, 1, 1, '_'); } - for (size_t pos = arg.find('<'); pos != string::npos; pos = arg.find('<')){ + for (size_t pos = arg.find('<'); pos != string::npos; pos = arg.find('<')) + { arg.replace(pos, 1, 1, '_'); } - for (size_t pos = arg.find('>'); pos != string::npos; pos = arg.find('>')){ + for (size_t pos = arg.find('>'); pos != string::npos; pos = arg.find('>')) + { arg.replace(pos, 1, 1, '_'); } return arg; @@ -72,20 +73,16 @@ std::string fix(const std::string userPath, const string& delimiters) string trimmedPath = trim(userPath, delimiters); string fixedPath; + char prev = 0; // In this loop, we check if there are more than one '/' together. If yes, // then accept only first one and reject other. for(unsigned int i = 0; i < trimmedPath.size(); ++i) { const char c = trimmedPath[i]; - if('/' == c) - { - if('/' != fixedPath[fixedPath.size()-1]) - fixedPath.push_back(c); - } - else + if(c != '/' || c != prev) fixedPath.push_back(c); - + prev = c; } return fixedPath; } @@ -94,36 +91,36 @@ int testTrim() { std::string testStrings [] = - { - " space at beginning", - "space at end ", - " space at both sides ", - "\ttab at beginning", - "tab at end\t", - "\ttab at both sides\t", - "\nnewline at beginning", - "newline at end\n", - "\nnewline at both sides\n", - "\n\tnewline and tab at beginning", - "space and tab at end \t", - " \rtab and return at both sides \r" - }; + { + " space at beginning", + "space at end ", + " space at both sides ", + "\ttab at beginning", + "tab at end\t", + "\ttab at both sides\t", + "\nnewline at beginning", + "newline at end\n", + "\nnewline at both sides\n", + "\n\tnewline and tab at beginning", + "space and tab at end \t", + " \rtab and return at both sides \r" + }; std::string results[] = - { - "space at beginning", - "space at end", - "space at both sides", - "tab at beginning", - "tab at end", - "tab at both sides", - "newline at beginning", - "newline at end", - "newline at both sides", - "newline and tab at beginning", - "space and tab at end", - "tab and return at both sides" - }; + { + "space at beginning", + "space at end", + "space at both sides", + "tab at beginning", + "tab at end", + "tab at both sides", + "newline at beginning", + "newline at end", + "newline at both sides", + "newline and tab at beginning", + "space and tab at end", + "tab and return at both sides" + }; bool success = true; @@ -140,7 +137,8 @@ int testTrim() bool endswith(const string & full, const string & ending) { - if (full.length() < ending.length()){ + if (full.length() < ending.length()) + { return false; } return (0 == full.compare(full.length() - ending.length(), ending.length(), ending)); @@ -159,4 +157,22 @@ int strncasecmp( const string& a, const string& b, size_t n) return 0; } +// This function is modification of this solution: +// https://stackoverflow.com/a/440240/1805129 +string random_string( const unsigned len ) +{ + static const char alphanum[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + + string s(len, '_' ); + for (unsigned i = 0; i < len; ++i) + { + s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + return s; +} + } diff --git a/moose-core/utility/strutil.h b/moose-core/utility/strutil.h index d6f48bfd7a85ba15d16c6202f12fbc5e1fd061d5..a5b1760b2c278fe7abde7aeaf52eab27e59bb38a 100644 --- a/moose-core/utility/strutil.h +++ b/moose-core/utility/strutil.h @@ -48,16 +48,10 @@ namespace moose */ int strncasecmp( const std::string& a, const std::string& b, size_t n); - - // TODO: other std::string utilities to add - // /** Trim leading and trailing whitespace and replace convert any two or more consecutive whitespace inside the std::string by a single 'blank' character. */ - // std::string fulltrim(std::string& myString) const; - // /** Convert to uppercase */ - // std::string upcase(std::string& myString) const; - // /** Convert to lowercase */ - // std::string downcase(std::string & myString); - // Maybe a implement regular expression search - reinventing wheel - but no standard way without using some bloated library. - + /** + * Generate random string of given length. + */ + std::string random_string( const unsigned size ); } #endif //_STRINGUTIL_H diff --git a/moose-core/utility/testing_macros.hpp b/moose-core/utility/testing_macros.hpp index 5d55dffca4ae9e4035dd028f6246fbc0e79abd02..87189889de3cc029dcd1bbded2972f5a6a693773 100644 --- a/moose-core/utility/testing_macros.hpp +++ b/moose-core/utility/testing_macros.hpp @@ -47,7 +47,7 @@ static ostringstream assertStream; assertStream.str(""); \ LOCATION( assertStream ); \ assertStream << msg << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_FALSE( condition, msg) \ @@ -55,7 +55,7 @@ static ostringstream assertStream; assertStream.str(""); \ LOCATION( assertStream ); \ assertStream << msg << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_EQ(a, b, token) \ @@ -64,7 +64,7 @@ static ostringstream assertStream; LOCATION(assertStream) \ assertStream << "Expected " << b << ", received " << a ; \ assertStream << token; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_NEQ(a, b, token) \ @@ -73,7 +73,7 @@ static ostringstream assertStream; LOCATION(assertStream); \ assertStream << "Not expected " << a << endl; \ assertStream << token << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_GT(a, b, token) \ @@ -82,7 +82,7 @@ static ostringstream assertStream; LOCATION(assertStream); \ assertStream << "Expected greater than " << a << ", received " << b << endl; \ assertStream << token << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_GTE(a, b, token) \ @@ -92,7 +92,7 @@ static ostringstream assertStream; assertStream << "Expected greater than or equal to " << a \ << ", received " << b << endl; \ assertStream << token << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_LT(a, b, token) \ @@ -101,7 +101,7 @@ static ostringstream assertStream; LOCATION(assertStream); \ assertStream << "Expected less than " << a << ", received " << b << endl; \ assertStream << token << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define EXPECT_LTE(a, b, token) \ @@ -111,7 +111,7 @@ static ostringstream assertStream; assertStream << "Expected less than or equal to " << a \ << ", received " << b << endl; \ assertStream << token << endl; \ - __dump__(assertStream.str(), "EXPECT_FAILURE"); \ + moose::__dump__(assertStream.str(), moose::failed); \ } #define ASSERT_TRUE( condition, msg) \ @@ -150,7 +150,7 @@ static ostringstream assertStream; if(! doubleEq(a, b) ) { \ assertStream.str(""); \ LOCATION(assertStream); \ - assertStream << "Expected " << b << ", received " << a << endl; \ + assertStream << "Expected " << std::fixed << b << ", received " << a << endl; \ assertStream << token; \ moose::__dump__(assertStream.str(), moose::failed); \ throw std::runtime_error( "float equality test failed" ); \ diff --git a/moose-core/utility/utility.h b/moose-core/utility/utility.h index 303de2774031b16a9fbd6c715f89ef568ca19c4e..4d5510186b9b682233feca04b3487979728cee7c 100644 --- a/moose-core/utility/utility.h +++ b/moose-core/utility/utility.h @@ -1,7 +1,5 @@ // utility.h --- -// -// Filename: utility.h -// Description: +// Description: Some utility function. // Author: Subhasis Ray // Maintainer: // Copyright (C) 2010 Subhasis Ray, all rights reserved. @@ -10,29 +8,14 @@ // Last-Updated: Tue Jul 23 12:48:17 2013 (+0530) // By: subha // Update #: 19 -// URL: -// Keywords: -// Compatibility: -// -// - -// Commentary: -// -// -// -// - -// Change log: -// -// -// - -// Code: #ifndef _UTILITY_H + #include "strutil.h" -namespace moose { +// See types.cpp file for definitions. +namespace moose +{ char shortType(std::string type); char innerType(char typecode); @@ -55,6 +38,5 @@ namespace moose { #endif // !_UTILITY_H - // // utility.h ends here