pax_global_header00006660000000000000000000000064142545761670014533gustar00rootroot0000000000000052 comment=8565d3c178a195a489fae0623d6338c2e92cd1e5 mod2c-8.2.2/000077500000000000000000000000001425457616700125505ustar00rootroot00000000000000mod2c-8.2.2/.github/000077500000000000000000000000001425457616700141105ustar00rootroot00000000000000mod2c-8.2.2/.github/workflows/000077500000000000000000000000001425457616700161455ustar00rootroot00000000000000mod2c-8.2.2/.github/workflows/mod2c-ci.yml000066400000000000000000000014411425457616700202650ustar00rootroot00000000000000name: MOD2C CI on: push: branches: - master pull_request: branches: - master env: BUILD_TYPE: RelWithDebInfo jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build - name: Configure CMake shell: bash working-directory: ${{runner.workspace}}/build run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ - name: Build working-directory: ${{runner.workspace}}/build shell: bash run: cmake --build . --config $BUILD_TYPE - name: Test working-directory: ${{runner.workspace}}/build shell: bash run: ctest -VV $BUILD_TYPE mod2c-8.2.2/.gitreview000066400000000000000000000001431425457616700145540ustar00rootroot00000000000000[gerrit] host=bbpcode.epfl.ch port=22 project=sim/mod2c defaultbranch=master defaultremote=origin mod2c-8.2.2/.travis.yml000066400000000000000000000003621425457616700146620ustar00rootroot00000000000000language: cpp compiler: gcc addons: apt: packages: - flex - bison - cmake before_script: - mkdir build - cd build - cmake .. -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ script: make && make test mod2c-8.2.2/AUTHORS.txt000066400000000000000000000003531425457616700144370ustar00rootroot00000000000000Adrien Devresse Aleksandr Ovcharenko Alexandru Săvulescu Bruno Magalhaes Ioannis Magkanaris Jeremy Fouriaux Michael Hines Nicolas Cornu Olli Lupton Omar Awile Pramod Kumbhar (maintainer) Sergio Rivas-Gomez Stuart Yates Timothee Ewart mod2c-8.2.2/CMake/000077500000000000000000000000001425457616700135305ustar00rootroot00000000000000mod2c-8.2.2/CMake/TestScriptUtils.cmake000066400000000000000000000103451425457616700176620ustar00rootroot00000000000000# Copyright (c) 2016, Blue Brain Project # 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. Neither the name of the copyright holder nor the names of its contributors # may 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 HOLDER 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. # Utility functions for manipulating test labels and producing # tests from scripts: # # 1. add_test_class(label [label2 ...]) # # Create a target with name test-label (or test-label-label2 etc.) # which runs only those tests possessing all of the supplied labels. # # # 2. add_test_label(name label ...) # # Add the given labels to the test 'name'. # # # 3. add_test_script(name script interp) # # Add a test 'name' that runs the given script, using the # interpreter 'interp'. If no interpreter is supplied, # the script will be run with /bin/sh. # # Uses the following variables to customize the new test: # * TEST_LABEL, ${NAME}_TEST_LABEL # If defined, apply the label(s) in these variable to the # new test. # * TEST_ARGS, ${NAME}_TEST_ARGS # Additional arguments to pass to the script. # ${NAME}_TEST_ARGS takes priority over TEST_ARGS. # * TEST_ENVIRONMENT # Additional environment variables to define for the test; # added to test properties. # * TEST_PREFIX, ${NAME}_TEST_PREFIX # If defined, preface the interpreter with this prefix. # ${NAME}_TEST_PREFIX takes priority over TEST_PREFIX. function(add_test_label NAME) set_property(TEST ${NAME} APPEND PROPERTY LABELS ${ARGN}) # create test classes for each label foreach(L ${ARGN}) add_test_class(${L}) endforeach() endfunction() function(add_test_script NAME SCRIPT INTERP) set(RUN_PREFIX ${TEST_PREFIX}) if(${NAME}_TEST_PREFIX) set(RUN_PREFIX ${${NAME}_TEST_PREFIX}) endif() if(NOT INTERP) set(INTERP "/bin/sh") endif() set(RUN_ARGS ${TEST_ARGS}) if (${NAME}_TEST_ARGS) set(RUN_ARGS ${${NAME}_TEST_ARGS}) endif() set(SCRIPT_PATH "${SCRIPT}") if(NOT IS_ABSOLUTE "${SCRIPT_PATH}") set(SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${SCRIPT_PATH}") endif() add_test(NAME ${NAME} COMMAND ${RUN_PREFIX} ${INTERP} "${SCRIPT_PATH}" ${RUN_ARGS} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") # Add test labels set(TEST_LABELS ${TEST_LABEL} ${${NAME}_TEST_LABEL}) if (TEST_LABELS) add_test_label(${NAME} ${TEST_LABELS}) endif() if(TEST_ENVIRONMENT) set_property(TEST ${NAME} PROPERTY ENVIRONMENT ${TEST_ENVIRONMENT}) endif() endfunction() function(add_test_class) string(REPLACE ";" "-" TEST_SUFFIX "${ARGN}") string(REPLACE ";" "$$;-L;^" TEST_LOPTS "${ARGN}") if(NOT TARGET test-${TEST_SUFFIX}) add_custom_target("test-${TEST_SUFFIX}" COMMAND ${CMAKE_CTEST_COMMAND} -L ^${TEST_LOPTS}$$ WORKING_DIRECTORY ${${PROJECT_NAME}_BINARY_DIR} COMMENT "Running all ${ARGN} tests") endif() endfunction() mod2c-8.2.2/CMake/config/000077500000000000000000000000001425457616700147755ustar00rootroot00000000000000mod2c-8.2.2/CMake/config/DefineInstallationPaths.cmake000066400000000000000000000147221425457616700225610ustar00rootroot00000000000000# Copyright (c) 2016, Blue Brain Project # 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. Neither the name of the copyright holder nor the names of its contributors # may 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 HOLDER 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. IF (UNIX) IF (NOT APPLICATION_NAME) MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME") SET(APPLICATION_NAME ${PROJECT_NAME}) ENDIF (NOT APPLICATION_NAME) # detect lib suffix GET_PROPERTY(LIB64_SUFFIX GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) IF(LIB64_SUFFIX) SET(LIB_SUFFIX "64" CACHE STRING "Suffix of the lib") ELSE() SET(LIB_SUFFIX "" CACHE STRING "Suffix of the lib") ENDIF() # correct cmake netpath issue with cmake 2.8 IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/") SET(INTERNAL_BASE_PREFIX "") ELSE("${CMAKE_INSTALL_PREFIX}" STREQUAL "/") SET(INTERNAL_BASE_PREFIX "${CMAKE_INSTALL_PREFIX}") ENDIF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/") SET(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries" ) SET(SHARE_INSTALL_PREFIX "${INTERNAL_BASE_PREFIX}/share" CACHE PATH "Base directory for files which go to share/" ) SET(DATA_INSTALL_PREFIX "${INTERNAL_BASE_PREFIX}/${APPLICATION_NAME}" CACHE PATH "The parent directory where applications can install their data") # The following are directories where stuff will be installed to SET(BIN_INSTALL_DIR "${INTERNAL_BASE_PREFIX}/bin" CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)" ) SET(SBIN_INSTALL_DIR "${INTERNAL_BASE_PREFIX}/sbin" CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)" ) SET(LIB_INSTALL_DIR "${INTERNAL_BASE_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)" ) SET(LIBEXEC_INSTALL_DIR "${INTERNAL_BASE_PREFIX}/libexec" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)" ) SET(PKGCONFIG_FILES_DIR "${LIB_INSTALL_DIR}/pkgconfig/" CACHE PATH "subdirectory relative to the install prefix where pkgconfig files (.pc) will be installed" ) SET(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/${APPLICATION_NAME}" CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})" ) SET(INCLUDE_INSTALL_DIR "${INTERNAL_BASE_PREFIX}/include" CACHE PATH "The subdirectory to the header prefix (default prefix/include)" ) SET(DATA_INSTALL_DIR "${DATA_INSTALL_PREFIX}" CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})" ) SET(DOC_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/doc/${APPLICATION_NAME}" CACHE PATH "The parent directory where applications can install their documentation (default prefix/share/doc/${APPLICATION_NAME})" ) SET(HTML_INSTALL_DIR "${DATA_INSTALL_PREFIX}/doc/HTML" CACHE PATH "The HTML install dir for documentation (default data/doc/html)" ) SET(ICON_INSTALL_DIR "${DATA_INSTALL_PREFIX}/icons" CACHE PATH "The icon install dir (default data/icons/)" ) SET(SOUND_INSTALL_DIR "${DATA_INSTALL_PREFIX}/sounds" CACHE PATH "The install dir for sound files (default data/sounds)" ) SET(LOCALE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/locale" CACHE PATH "The install dir for translations (default prefix/share/locale)" ) SET(XDG_APPS_DIR "${SHARE_INSTALL_PREFIX}/applications/" CACHE PATH "The XDG apps dir" ) SET(XDG_DIRECTORY_DIR "${SHARE_INSTALL_PREFIX}/desktop-directories" CACHE PATH "The XDG directory" ) SET(SYSCONF_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/etc" CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" ) SET(MAN_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/man" CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)" ) SET(INFO_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/info" CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)" ) ENDIF (UNIX) if (WIN32) # Same same SET(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries" ) set(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "-") set(SBIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "-") set(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "-") set(INCLUDE_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/include" CACHE PATH "-") SET(SYSCONF_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/etc" CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" ) SET(PKGCONFIG_FILES_DIR "${EXEC_INSTALL_PREFIX}/lib/pkgconfig/" CACHE PATH "subdirectory relative to the install prefix where pkgconfig files (.pc) will be installed" ) set(PLUGIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin/plugins" CACHE PATH "-") set(HTML_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/doc/HTML" CACHE PATH "-") set(ICON_INSTALL_DIR "." CACHE PATH "-") set(SOUND_INSTALL_DIR "." CACHE PATH "-") set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-") endif (WIN32) mod2c-8.2.2/CMake/config/ReleaseDebugAutoFlags.cmake000066400000000000000000000043071425457616700221400ustar00rootroot00000000000000# Copyright (c) 2016, Blue Brain Project # 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. Neither the name of the copyright holder nor the names of its contributors # may 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 HOLDER 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. ## debug / release autoManagement ## default configuration if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE}' as none was specified.") endif() set(STACK_PROTECTION_FLAGS "") if(CMAKE_COMPILER_IS_GNUCC) set(STACK_PROTECTION_FLAGS "-fstack-protector-all") endif() set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-g ${STACK_PROTECTION_FLAGS}") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2") set(CMAKE_CXX_FLAGS_RELEASE "-O2") set(CMAKE_CXX_FLAGS_DEBUG "-g ${STACK_PROTECTION_FLAGS} ") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O2") mod2c-8.2.2/CMakeLists.txt000066400000000000000000000054531425457616700153170ustar00rootroot00000000000000# Copyright (c) 2016, Blue Brain Project # 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. Neither the name of the copyright holder nor the names of its contributors # may 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 HOLDER 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. cmake_minimum_required(VERSION 3.15) set(CMAKE_BUILD_TYPE Release) project(mod2c VERSION 2.1.0) set(MOD2C_DESCRIPTION "MOD2C converter") set(VERSION_STRING "${PROJECT_VERSION}") # put mod2c_core in /bin of the project of which # this is a subproject set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) option(UNIT_TESTS "Enable unit tests compilation and execution" FALSE) option(FUNCTIONAL_TESTS "Enable functional tests compilation and execution" FALSE) option(MOD2C_ENABLE_LEGACY_UNITS "Enable old definition for units" OFF) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake ${PROJECT_SOURCE_DIR}/CMake/config) include(DefineInstallationPaths) include(ReleaseDebugAutoFlags) find_package(BISON REQUIRED) find_package(FLEX REQUIRED) if(MINGW) add_definitions("-DMINGW") endif() add_subdirectory(src/mod2c_core) # Disable tests if we are a sub project if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) include(CTest) add_subdirectory(test/validation) endif() if (MOD2C_ENABLE_LEGACY_UNITS) set(LegacyY "") set(LegacyN "/") else() set(LegacyY "/") set(LegacyN "") endif() configure_file(share/nrnunits.lib.in ${CMAKE_BINARY_DIR}/share/mod2c/nrnunits.lib @ONLY) install(FILES ${CMAKE_BINARY_DIR}/share/mod2c/nrnunits.lib DESTINATION share/mod2c) mod2c-8.2.2/LICENSE.txt000066400000000000000000000027351425457616700144020ustar00rootroot00000000000000Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. mod2c-8.2.2/README.md000066400000000000000000000036011425457616700140270ustar00rootroot00000000000000# MOD2C > NMODL to C converter for CoreNEURON [![Build Status](https://travis-ci.org/BlueBrain/mod2c.svg?branch=master)](https://travis-ci.org/BlueBrain/mod2c) [![MOD2C CI](https://github.com/BlueBrain/mod2c/workflows/MOD2C%20CI/badge.svg)](https://github.com/BlueBrain/mod2c/actions?query=workflow%3A%22MOD2C+CI%22) MOD2C is NMODL to C adapted for [CoreNEURON simulator](https://github.com/BlueBrain/CoreNEURON). More information about NMODL can be found [here](https://www.neuron.yale.edu/neuron/static/docs/refman/nocmodl.html). This version supports GPU code generation using OpenACC. Use latest version of CoreNeuron. # Requirements * [CMake 2.8.9+](https://cmake.org/) * [Flex](http://flex.sourceforge.net) * [Bison](https://www.gnu.org/software/bison/) # Installation Once you clone the repository, you can build mod2c using CMake as follows: ```bash cd mod2c mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=/path/to/install/directory make make install ``` Note that mod2c is used only during the compilation phase of the CoreNEURON simulator and hence should be built only for the front-end/login nodes in cross-compile environments like BG-Q, Cray, Intel MIC etc. # Funding & Acknowledgment The development of this software was supported by funding to the Blue Brain Project, a research center of the École polytechnique fédérale de Lausanne (EPFL), from the Swiss government's ETH Board of the Swiss Federal Institutes of Technology. Copyright © 2015-2022 Blue Brain Project/EPFL ## License * See LICENSE.txt * See [NEURON](https://www.neuron.yale.edu/neuron/) * The mechanisms and test datasets appearing in the CoreNeuron repository are subject to separate licenses. More information is available on the NMC portal website [NMC portal](https://bbp.epfl.ch/nmc-portal/copyright), the specific licenses are described in the ME-type model packages downloadable from that website. mod2c-8.2.2/share/000077500000000000000000000000001425457616700136525ustar00rootroot00000000000000mod2c-8.2.2/share/nrnunits.lib.in000077500000000000000000000251021425457616700166320ustar00rootroot00000000000000/ from gnu units distribution / Nov, 2017 updated faraday, R, e, planck, hbar, mole, k according to / https://physics.nist.gov/cuu/Constants/index.html / primitive units m *a* kg *b* sec *c* coul *d* candela *e* dollar *f* bit *h* erlang *i* K *j* / prefixes /yotta- 1e24 /zetta- 1e21 /exa- 1e18 /peta- 1e15 /tera- 1e12 /giga- 1e9 /mega- 1e6 /myria- 1e4 /kilo- 1e3 /hecto- 1e2 /deka- 1e1 /deci- 1e-1 /centi- 1e-2 /milli- 1e-3 /micro- 1e-6 /nano- 1e-9 /pico- 1e-12 /femto- 1e-15 /atto- 1e-18 /zopto- 1e-21 /yocto- 1e-24 / /semi- .5 /demi- .5 / /Y- yotta /Z- zetta /E- exa /P- peta /T- tera /G- giga /M- mega /k- kilo /h- hecto /da- deka /d- deci /c- centi /m- milli /p- pico /f- femto /a- atto /z- zopto /y- yocto / constants fuzz 1 two 2 pi 3.14159265358979323846 c 2.99792458+8 m/sec fuzz g 9.80665 m/sec2 au 1.49597871+11 m fuzz @LegacyY@mole 6.022169+23 fuzz @LegacyN@mole 6.02214076+23 fuzz @LegacyY@e 1.6021917-19 coul fuzz @LegacyN@e 1.602176634-19 coul fuzz energy c2 force g mercury 1.33322+5 kg/m2-sec2 hg mercury / dimensionless radian .5 / pi degree 1|180 pi-radian circle 2 pi-radian turn 2 pi-radian revolution turn rev turn grade .9 degree arcdeg 1 degree arcmin 1|60 arcdeg ccs 1|36 erlang arcsec 1|60 arcmin steradian radian2 sphere 4 pi-steradian sr steradian / Time second sec s sec minute 60 sec min minute hour 60 min hr hour day 24 hr da day week 7 day year 365.24219879 day fuzz yr year month 1|12 year ms millisec us microsec / Mass gram millikg gm gram mg milligram metricton kilokg / Avoirdupois lb .45359237 kg pound lb lbf lb g ounce 1|16 lb oz ounce dram 1|16 oz dr dram grain 1|7000 lb gr grain shortton 2000 lb ton shortton longton 2240 lb / Apothecary scruple 20 grain apdram 60 grain apounce 480 grain appound 5760 grain troypound appound / Length meter m cm centimeter mm millimeter km kilometer nm nanometer micron micrometer angstrom decinanometer inch 2.54 cm in inch foot 12 in feet foot ft foot yard 3 ft yd yard rod 5.5 yd rd rod mile 5280 ft mi mile british 1200|3937 m/ft nmile 1852m acre 4840 yd2 cc cm3 liter kilocc ml milliliter / US Liquid gallon 231 in3 imperial 1.20095 gal gallon quart 1|4 gal qt quart pint 1|2 qt pt pint floz 1|16 pt fldr 1|8 floz / US Dry dry 268.8025 in3/gallon fuzz peck 8 dry-quart pk peck bushel 4 peck bu bushel chaldron 36 bushel / British brgallon 277.420 in3 fuzz brquart 1|4 brgallon brpint 1|2 brquart brfloz 1|20 brpint brpeck 554.84 in3 fuzz brbushel 4 brpeck / Energy Work newton kg-m/sec2 nt newton N newton joule nt-m cal 4.1868 joule / Electrical coulomb coul C coul ampere coul/sec amp ampere watt joule/sec volt watt/amp ohm volt/amp mho /ohm farad coul/volt henry sec2/farad weber volt-sec / Light cd candela lumen cd sr lux cd sr/m2 / Wall Street Journal, July 2, 1993 $ dollar argentinapeso $ australiadollar .66 $ austriaschilling .83 $ bahraindinar 2.6522 $ belgiumfranc .028 $ brazilcruzeiro .000019 $ britainpound 1.49 $ canadadollar .77 $ czechkoruna .034 $ chilepeso .0025 $ chinarenminbi .174856 $ colombiapeso .001495 $ denmarkkrone .15 $ ecuadorsucre .000539 $ finlandmarkka .17 $ francefranc .17 $ germanymark .58 $ greatbritainpound britainpound greecedrachma .0043 $ hongkongdollar .13 $ hungaryforint .011 $ indiarupee .03211 $ indonesiarupiah .0004782 $ irelandpunt 1.43 $ israelshekel .3642 $ italylira .00064 $ japanyen .0093 $ jordandinar 1.4682 $ kuwaitdinar 3.3173 $ lebanonpound .000578 $ malaysiaringgit .338 $ maltalira 2.6042 $ mexicopeso .3205128 $ netherlandsguilder .52 $ newzealanddollar .539 $ norwaykrone .139 $ pakistanrupee .037 $ perunewsol .5065 $ philippinespeso .03738 $ polandzloty .000059 $ portugalescudo .00617 $ saudiarabiariyal .26702 $ singaporedollar .6157 $ slovakkoruna .034 $ southafricarand .21 $ southkoreawon .001 $ spainpeseta .007 $ swedenkrona .13 $ switzerlandfranc .66 $ taiwandollar .038285 $ thailandbaht .03962 $ turkeylira .0000929 $ unitedarabdirham .2723 $ uruguaynewpeso .246852 $ venezuelabolivar .011 $ mark germanymark bolivar venezuelabolivar peseta spainpeseta rand southafricarand escudo portugalescudo sol perunewsol guilder netherlandsguilder hollandguilder netherlandsguilder peso mexicopeso yen japanyen lira italylira rupee indiarupee drachma greecedrachma franc francefranc markka finlandmarkka sucre ecuadorsucre poundsterling britainpound cruzeiro brazilcruzeiro / computer baud bit/sec byte 8 bit block 512 byte kbyte 1024 byte megabyte 1024 kbyte gigabyte 1024 megabyte meg megabyte / Trivia % 1|100 admiraltyknot 6080 ft/hr apostilb cd/pi-m2 are 1+2 m2 arpentcan 27.52 mi arpentlin 191.835 ft astronomicalunit au atmosphere 1.01325+5 nt/m2 atm atmosphere atomicmassunit 1.66044-27 kg fuzz amu atomicmassunit bag 94 lb bakersdozen 13 bar 1+5 nt/m2 barie 1-1 nt/m2 barleycorn 1|3 in barn 1-28 m2 barrel 42 gal barye 1-1 nt/m2 bev 1+9 e-volt biot 10 amp blondel cd/pi-m2 boardfoot 144 in3 bolt 40 yd bottommeasure 1|40 in britishthermalunit 1.05506+3 joule fuzz btu britishthermalunit refrigeration 12000 btu/ton-hour buck dollar cable 720 ft caliber 1-2 in calorie cal carat 205 mg caratgold 1|24 cent centidollar cental 100 lb centesimalminute 1-2 grade centesimalsecond 1-4 grade century 100 year cfs ft3/sec chain 66 ft circularinch 1|4 pi-in2 circularmil 1-6|4 pi-in2 clusec 1-8 mm-hg m3/s coomb 4 bu cord 128 ft3 cordfoot cord crith 9.06-2 gm cubit 18 in cup 1|2 pt curie 3.7+10 /sec dalton amu decade 10 yr dipotre /m displacementton 35 ft3 doppelzentner 100 kg dozen 12 drop .03 cm3 dyne cm-gm/sec2 electronvolt e-volt ell 45 in engineerschain 100 ft engineerslink 100|100 ft equivalentfootcandle lumen/pi-ft2 equivalentlux lumen/pi-m2 equivalentphot cd/pi-cm2 erg cm2-gm/sec2 ev e-volt / faraday 9.652000+04 coul / faraday from host: physics.nist.gov / path: /PhysRefData/fundconst/html/keywords.html @LegacyY@faraday 9.6485309+4 coul @LegacyN@faraday e-mole fathom 6 ft fermi 1-15 m fifth 4|5 qt fin 5 dollar finger 7|8 in firkin 9 gal footcandle lumen/ft2 footlambert cd/pi-ft2 fortnight 14 da franklin 3.33564-10 coul frigorie kilocal furlong 220 yd galileo 1-2 m/sec2 gamma 1-9 weber/m2 gauss 1-4 weber/m2 geodeticfoot british-ft geographicalmile 1852 m gilbert 7.95775-1 amp gill 1|4 pt gross 144 gunterschain 22 yd hand 4 in hectare 1+4 m2 hefnercandle .92 cd hertz /sec Hz hertz hogshead 2 barrel hd hogshead homestead 1|4 mi2 horsepower 550 ft-lb-g/sec hp horsepower hyl gm force sec2/m hz /sec imaginarycubicfoot 1.4 ft3 jeroboam 4|5 gal @LegacyY@boltzmann 1.38064852-23 joule/K @LegacyN@boltzmann 1.380649-23 joule/K k boltzmann karat 1|24 kcal kilocal kcalorie kilocal kev 1+3 e-volt key kg khz 1+3 /sec kilderkin 18 gal knot nmile/hr lambert cd/pi-cm2 langley cal/cm2 last 80 bu league 3 mi lightyear c-yr line 1|12 in link 66|100 ft longhundredweight 112 lb longquarter 28 lb lusec 1-6 mm-hg m3/s mach 331.46 m/sec magnum 2 qt marineleague 3 nmile maxwell 1-8 weber metriccarat 200 mg mgd megagal/day mh millihenry mhz 1+6 /sec mil 1-3 in millenium 1000 year minersinch 1.5 ft3/min minim 1|60 fldr mo month mpg mile/gal mph mile/hr nail 1|16 yd nauticalmile nmile nit cd/m2 noggin 1|8 qt nox 1-3 lux ns nanosec oersted 2.5+2 pi-amp/m oe oersted pace 36 in palm 3 in parasang 3.5 mi parsec au-radian/arcsec pascal nt/m2 pc parsec pennyweight 1|20 oz pwt pennyweight percent % perch rd pf picofarad phot lumen/cm2 pica 1|6 in pieze 1+3 nt/m2 pipe 4 barrel point 1|72 in poise gm/cm-sec pole rd poundal ft-lb/sec2 pdl poundal proof 1|200 psi lb-g/in2 quarter 9 in quartersection 1|4 mi2 quintal 100 kg quire 25 @LegacyY@gasconstant 8.3144598 joule/K @LegacyN@gasconstant k-mole R gasconstant rad 100 erg/gm ream 500 registerton 100 ft3 rehoboam 156 floz rhe 10 m2/nt-sec rontgen 2.58-4 curie/kg rood 1.21+3 yd rope 20 ft rutherford 1+6 /sec rydberg 1.36054+1 ev sabin 1 ft2 sack 3 bu seam 8 bu section mi2 shippington 40 ft3 shorthundredweight 100 lb shortquarter 25 lb siemens /ohm sigma microsec skein 120 yd skot 1-3 apostilb slug lb-g-sec2/ft span 9 in spat 4 pi sr spindle 14400 yd square 100 ft2 stere m3 sthene 1+3 nt stilb cd/cm2 stoke 1-4 m2/sec stone 14 lb strike 2 bu surveyfoot british-ft surveyyard 3 surveyfoot surveyorschain 66 ft surveyorslink 66|100 ft tablespoon 4 fldr teaspoon 4|3 fldr tesla weber/m2 therm 1+5 btu thermie 1+6 cal timberfoot ft3 tnt 4.6+6 m2/sec2 tonne 1+6 gm torr mm hg township 36 mi2 tun 8 barrel water gram g / cc wey 40 bu weymass 252 lb Xunit 1.00202-13m degC K kelvin K brewster 1-12 m2/newton degF 5|9 degC degreesrankine degF degrankine degreesrankine degreerankine degF degreaumur 10|8 degC drachm 60 grain poncelet 100 kg m g / sec denier .05|450 gram / m tex .001 gram / m englishell 45 inch scottishell 37.2 inch flemishell 27 inch @LegacyY@planck 6.626-34 joule-sec @LegacyN@planck 6.62607015-34 joule-sec @LegacyY@hbar 1.055-34 joule-sec @LegacyN@hbar planck/two-pi electronmass 9.1095-31 kg protonmass 1.6726-27 kg neutronmass 1.6606-27 kg V volt eV e V bohrradius 1|8.988e9 hbar2-C2 / N m2-e2-electronmass becquerel 1|3.7+10 curie fresnel 1+12 hertz statcoul 1|2.99792458+9 coul statamp 1|2.99792458+9 amp statvolt 2.99792458+2 volt statcoulomb statcoul statampere statamp debye 3.336-30 coul-m pulsatance 2 pi/sec rpm rev/minute rps rev/sec kilohm kiloohm megohm megaohm siderealyear 365.256360417 day siderealday 23.934469444 hour siderealhour 1|24 siderealday lunarmonth 29.5305555 day synodicmonth lunarmonth siderealmonth 27.32152777 day tropicalyear year solaryear year lunaryear 12 lunarmonth cran 37.5 brgallon kip 1000 lbf frenchfoot 16|15 ft frenchfeet frenchfoot toise 6 frenchfeet sievert 8.4 rontgen candle 1.02 candela militarypace 2.5 feet metre meter litre liter gramme gram iudiptheria 62.8 microgram iupenicillin .6 microgram iuinsulin 41.67 microgram cottonyarncount 2520 ft/pound linenyarncount 900 ft/pound worstedyarncount 1680 ft/pound metricyarncount meter/gram jewlerspoint 2 milligram mod2c-8.2.2/src/000077500000000000000000000000001425457616700133375ustar00rootroot00000000000000mod2c-8.2.2/src/mod2c_core/000077500000000000000000000000001425457616700153535ustar00rootroot00000000000000mod2c-8.2.2/src/mod2c_core/CMakeLists.txt000066400000000000000000000117131425457616700201160ustar00rootroot00000000000000# Copyright (c) 2016-2022, Blue Brain Project # 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. Neither the name of the copyright holder nor the names of its contributors # may 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 HOLDER 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. set(NOCMODL_CORE_SOURCES "consist.c" "io.c" "list.c" "nocpout.c" "partial.c" "solve.c" "version.c" "discrete.c" "kinetic.c" "modl.c" "parsact.c" "sens.c" "symbol.c" "deriv.c" "init.c" "noccout.c" "simultan.c" "units.c" ) file(RELATIVE_PATH CUR_SRC_REL "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}") add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/diffeq.c" "${CMAKE_CURRENT_BINARY_DIR}/diffeq.h" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${BISON_EXECUTABLE}" ARGS --defines=diffeq.h -o diffeq.c "${CUR_SRC_REL}/diffeq.y" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/diffeq.y" COMMENT "[BISON][diffeq] Building parser with bison ${BISON_VERSION}") add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/parse1.c" "${CMAKE_CURRENT_BINARY_DIR}/parse1.h" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${BISON_EXECUTABLE}" ARGS --defines=parse1.h -o parse1.c "${CUR_SRC_REL}/parse1.y" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/parse1.y" COMMENT "[BISON][parse1] Building parser with bison ${BISON_VERSION}") add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/lex.c" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${FLEX_EXECUTABLE}" ARGS -o lex.c "${CUR_SRC_REL}/lex.l" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/lex.l" "${CMAKE_CURRENT_BINARY_DIR}/parse1.h" COMMENT "[FLEX][lex] Building scanner with flex ${FLEX_VERSION}") if(MOD2C_ENABLE_LEGACY_UNITS) set(USE_LEGACY_UNITS 1) else() set(USE_LEGACY_UNITS 0) endif() add_definitions(-DNMODL=1 -DBBCORE=1 -DNOCMODL=1 -DCVODE=1 -DVECTORIZE=1 -DUSE_LEGACY_UNITS=${USE_LEGACY_UNITS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) add_executable( mod2c_core ${NOCMODL_CORE_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/diffeq.c" "${CMAKE_CURRENT_BINARY_DIR}/parse1.c" "${CMAKE_CURRENT_BINARY_DIR}/lex.c") # as mod2c is typically executed on front-end node, in order to avoid runtime # issues from platform specific optimisations, build mod2c with debug flags # as performance is not a concern (for translating mod files to cpp) separate_arguments(NMODL_C_FLAGS UNIX_COMMAND "${CMAKE_CXX_FLAGS_DEBUG}") if(CMAKE_C_COMPILER_ID STREQUAL "PGI" OR CMAKE_C_COMPILER_ID STREQUAL "NVHPC") if(CMAKE_C_COMPILER_VERSION VERSION_LESS 20.7) # Taken from CoreNEURON's OpenAccHelper.cmake list(APPEND NMODL_C_FLAGS --diag_suppress=161,177,550) else() # https://forums.developer.nvidia.com/t/many-all-diagnostic-numbers-increased-by-1-from-previous-values/146268/3 # changed the numbering scheme in newer versions. The following list is from a clean start 13 # August 2021. # Examples of the suppressed warnings are given below. # ~~~ # "src/mod2c_core/kinetic.c", warning #111-D: statement is unreachable # "src/mod2c_core/parsact.c", warning #128-D: loop is not reachable # "src/mod2c_core/units.c", warning #170-D: pointer points outside of underlying object # "src/mod2c_core/parsact.c", warning #177-D: variable "qq" was declared but never referenced # "src/mod2c_core/kinetic.c", warning #550-D: variable "qv" was set but never used # "src/mod2c_core/sens.c", warning #1052-D: standard requires that parameter "fn" be given a type by a subsequent declaration ("int" assumed) # ~~~ list(APPEND NMODL_C_FLAGS --diag_suppress=111,128,170,177,550,1052) endif() endif() target_compile_options(mod2c_core PRIVATE ${NMODL_C_FLAGS}) install(TARGETS mod2c_core DESTINATION bin) mod2c-8.2.2/src/mod2c_core/carbonnmodl.h000077500000000000000000000003151425457616700200240ustar00rootroot00000000000000#include #include #include #include #pragma once off #define SYSV 1 #define MAC 1 #define NMODL 1 #define NOCMODL 1 #define VECTORIZE 1 #define CVODE 1 mod2c-8.2.2/src/mod2c_core/consist.c000066400000000000000000000070621425457616700172060ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* * Check that names do not have conflicting types. This is done after the * entire file is read in and allows declaring a variable after its use (very * bad style) to work in some circumstances. */ #include "modl.h" #include "parse1.h" #include "symbol.h" extern Symbol *scop_indep; extern Symbol *indepsym; #define con(arg1,arg2,arg3) if (t & (arg2)) if (t & (~(arg2 | arg3))) {\ Fprintf(stderr, "%s is a %s\n",\ s->name, arg1);\ err=1;\ } void consistency() { Symbol *s; Item *qs; int i, tu, err = 0; long t; /* the scop_indep can also be a automatic parameter */ if (scop_indep != indepsym && scop_indep->subtype == (PARM | INDEP)) { scop_indep->subtype = INDEP; } SYMITER(NAME) { t = s->subtype; con("KEYWORD", KEYWORD, 0); con("RESERVED WORD", EXTDEF|EXTDEF2|EXTDEF3|EXTDEF4|EXTDEF5, 0); con("CONSTANT", nmodlCONST, 0); con("PARAMETER", PARM, ARRAY); con("ASSIGNED", DEP, ARRAY); con("INDEPENDENT", INDEP, 0); con("STATE", STAT, ARRAY); con("FUNCTION", FUNCT, 0); con("PROCEDURE", PROCED, 0); con("DERIVATIVE", DERF, 0); con(" KINETIC", KINF, 0); con("LINEAR", LINF, 0); con("NONLINEAR", NLINF, 0); con("DISCRETE", DISCF, 0); con("PARTIAL", PARF, 0); con("STEPPED", STEP1, 0); con("CONSTANT UNITS FACTOR", UNITDEF, 0); tu = s->usage; if ((tu & DEP) && (tu & FUNCT)) diag(s->name, " used as both variable and function"); if ((t == 0) && tu) Fprintf(stderr, "Warning: %s undefined. (declared within VERBATIM?)\n", s->name); } if (err) { diag("multiple uses for same variable", (char *) 0); } if (indepsym == SYM0) { diag("Independent variable is not defined", (char *)0); } /* avoid the problem where person inadvertently is using Dstate as a state*/ SYMITER(NAME) { if ((s->subtype & STAT) && (s->name[0] == 'D')) { Symbol* s1 = lookup(s->name + 1); if (s1 && s->type == NAME && (s->subtype & STAT)) { fprintf(stderr, "%s is a STATE so %s is a %s' and", s1->name, s->name, s1->name); diag(" cannot be declared as a STATE\n", (char*)0); } } } } mod2c-8.2.2/src/mod2c_core/deriv.c000066400000000000000000001076601425457616700166420ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" #include "modl.h" #include "symbol.h" #include #undef METHOD #include "parse1.h" static List *deriv_imp_list; /* list of derivative blocks that were translated in form suitable for the derivimplicit method */ static List *deriv_imp_really; /* derivative blocks solved by derivimplicit */ static char Derivimplicit[] = "derivimplicit"; extern Symbol *indepsym; extern List *indeplist; extern int sens_parm, numlist; static void copylist(); List* massage_list_; #if VECTORIZE extern int vectorize; extern int assert_threadsafe; extern int thread_data_index; extern List* thread_mem_init_list; extern List* thread_cleanup_list; extern List* newtonspace_list; #endif #if CVODE extern char* cvode_deriv(), *cvode_eqnrhs(); extern Item* cvode_cnexp_solve; static void cvode_diffeq(); static List* cvode_diffeq_list, *cvode_eqn; static int cvode_cnexp_possible; #endif int derivimplic_listnum; void solv_diffeq(qsol, fun, method, numeqn, listnum, steadystate, btype) Item *qsol; Symbol *fun, *method; int numeqn, listnum, steadystate; int btype; { char *maxerr_str, dindepname[50]; char ssprefix[8]; if (method && strcmp(method->name, "cnexp") == 0) { sprintf(buf, " %s();\n", fun->name); replacstr(qsol, buf); sprintf(buf, " %s(_threadargs_);\n", fun->name); vectorize_substitute(qsol, buf); return; } if (steadystate) { Strcpy(ssprefix, "_ss_"); }else{ Strcpy(ssprefix, ""); } Sprintf(dindepname, "d%s", indepsym->name); if (fun->subtype & KINF) { /* translate the kinetic equations */ /* can be standard integrator, full matrix advancec, or sparse matrix advance */ /* at this time only sparse and standard exists */ if (method->subtype & DERF) { kinetic_intmethod(fun, method->name); } else { kinetic_implicit(fun, dindepname, method->name); } } save_dt(qsol); if (method->subtype & DERF) { if (method->u.i == 1) { /* variable step method */ maxerr_str = ", maxerr"; IGNORE(ifnew_parminstall("maxerr", "1e-5", "", "")); } else { maxerr_str = ""; } if (deriv_imp_list) { /* make sure deriv block translation matches method */ Item *q; int found=0; ITERATE(q, deriv_imp_list) { if (strcmp(STR(q), fun->name) == 0) { found = 1; } } if ((strcmp(method->name, Derivimplicit) == 0) ^ (found == 1)) { diag("To use the derivimplicit method the SOLVE statement must\ precede the DERIVATIVE block\n", " and all SOLVEs using that block must use the derivimplicit method\n"); } derivimplic_listnum = listnum; Sprintf(buf, "static int _deriv%d_advance = 1;\n", listnum); q = linsertstr(procfunc, buf); Sprintf(buf, "\n#define _deriv%d_advance _thread[%d]._i\n\ #define _dith%d %d\n#define _newtonspace%d _thread[%d]._pvoid\n\ ", listnum, thread_data_index, listnum, thread_data_index+1, listnum, thread_data_index+2); vectorize_substitute(q, buf); Sprintf(buf, " _thread[_dith%d]._pval = NULL;", listnum); lappendstr(thread_mem_init_list, buf); Sprintf(buf, " if (!_newtonspace%d) {\n" " _newtonspace%d = nrn_cons_newtonspace(%d, _cntml_padded);\n" " _thread[_dith%d]._pval = makevector(2*%d*_cntml_padded*sizeof(double));\n" " #ifdef _OPENACC\n" " if (_nt->compute_gpu) {\n" " void* _d_ns = (void*)acc_deviceptr(_newtonspace%d);\n" " double* _d_pd = (double*)acc_copyin(_thread[_dith%d]._pval,2*%d*_cntml_padded* sizeof(double));\n" " ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread);\n" " acc_memcpy_to_device(&(_d_td[%d]._pvoid), &_d_ns, sizeof(void*));\n" " acc_memcpy_to_device(&(_d_td[_dith%d]._pval), &_d_pd, sizeof(double*));\n" " }\n" " #endif\n" " }\n" , listnum, listnum, numeqn, listnum, numeqn , listnum, listnum, numeqn, thread_data_index+2, listnum ); lappendstr(newtonspace_list, buf); Sprintf(buf, " free( _thread[_dith%d]._pval);\n", listnum); lappendstr(thread_cleanup_list, buf); Sprintf(buf, " nrn_destroy_newtonspace((NewtonSpace*) _newtonspace%d);\n", listnum); lappendstr(thread_cleanup_list, buf); thread_data_index += 3; } Sprintf(buf," %s%s(_ninits, %d, _slist%d, _dlist%d, _p, &%s, %s, %s, &_temp%d%s);", ssprefix, method->name, numeqn, listnum, listnum, indepsym->name, dindepname, fun->name, listnum, maxerr_str); }else{ Sprintf(buf, " if (!_thread[_spth%d]._pvoid) {\n" " _thread[_spth%d]._pvoid = nrn_cons_sparseobj(%s%s{}, %d, _ml, _threadargs_);\n" " #ifdef _OPENACC\n" " if (_nt->compute_gpu) {\n" " void* _d_so = (void*) acc_deviceptr(_thread[_spth%d]._pvoid);\n" " ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread);\n" " acc_memcpy_to_device(&(_d_td[_spth%d]._pvoid), &_d_so, sizeof(void*));\n" " }\n" " #endif\n" " }\n" , listnum, listnum, fun->name, suffix, numeqn , listnum, listnum ); lappendstr(newtonspace_list, buf); Sprintf(buf, "%s%s(&_sparseobj%d, %d, _slist%d, _dlist%d, _p, &%s, %s, %s\ ,&_coef%d, _linmat%d);\n", ssprefix, method->name, listnum, numeqn, listnum, listnum, indepsym->name, dindepname, fun->name, listnum, listnum); } replacstr(qsol, buf); #if VECTORIZE if (method->subtype & DERF) { /* derivimplicit */ Sprintf(buf, "\n %s%s_thread(%d, _slist%d, _dlist%d, %s%s{}, _threadargs_);\n", ssprefix, method->name, numeqn, listnum, listnum, fun->name, suffix); vectorize_substitute(qsol, buf); }else{ /* kinetic */ if (vectorize) { Sprintf(buf, "\n %s%s_thread(static_cast(_thread[_spth%d]._pvoid), %d, _slist%d, _dlist%d, &%s, %s, %s%s{}, _linmat%d, _threadargs_);\n", ssprefix, method->name, listnum, numeqn, listnum, listnum, indepsym->name, dindepname, fun->name, suffix, listnum); vectorize_substitute(qsol, buf); } #endif } } /* addition of higher order derivatives User appearance: Higher order derivatives are now allowed in DERIVATIVE blocks. The number of primes following a variable is the order of the derivative. For example, y'''' is a 4th order derivative. The highest derivative of a state must appear on the left hand side of the equation. Lower order derivatives of a state (including the state itself) may appear on the right hand side within an arbitrary expression. It makes no sense, in general, to have multiple equations involving the same state on the left hand side. The most common usage will be equations of the form y'' = f(y, y', t) Higher derivatives can be accessed in SCoP as y' Dy y'' D2y y''' D3y etc. Note that all derivatives except the highest derivative are themselves states on an equal footing with y. E.G. they can be used within a MATCH block, they can be explicitly declared within a STATE block (and given START values), and they have associated initial value constants. Initial values default to 0. Here is a complicated example which shows off the syntax (I have no idea if the solution exists). INDEPENDENT {t FROM 0 TO 1 WITH 1} STATE {x y y' START 1 x' START -10 } DERIVATIVE d { x''' = y + 3*x''*y' + sin(x') + exp(x) y'' = cos(x'' + y) - y' MATCH { y0 y(1)=1 x(1)=1 Dx0 x''(1)=0 } EQUATION {SOLVE d} Note that we had to use Dx0 since x'0 is illegal. Also Dx0 has a value of -10. Implementation : In parse1.y we see that asgn: varname '=' expr and that varname gets marked if it is type PRIME. With respect to higher order derivatives, therefore, only the highest order actually used in the equations in that block should be marked. Furthermore these highest primes may or may not be dependent variables and the lesser primes must be created as states. We use a special iterator FORALL which returns each lesser order symbol given a dstate. The implicit equations of the form DD2y = D3y do not have to be constructed and the dependent variables DD2y do not have to be created since the slist and dlist links can carry this information. Thus dlist[D2y] == slist[D3y] causes the integrators to do the right thing without, in fact, doing any arithmetic. We assume that the itegrators either save the *dlist values or update *slist using a loop running from 0 to N. This is why the FORALL interator returns states starting with the base state (so that *slist[i+1] doesn't change until after *dlist[i] is used. (they point to the same value). In the case of a second order equation, the lists are: slist[0] = &y dlist[0] = &Dy slist[1] = &Dy dlist[1] = &D2y With respect to the MATCH process the code which unmarks the PRIMES and marks the corresponding state is inadequate since several states must be marked some of which are PRIME. For this reason we distinguish using a -1 to mark states for later counting. The array problem is solved by using lex to: when a PRIME is seen, check against the base state. If the base state doesn't exist don't worry. If the STATE is an array Then make PRIME an array of the same dimension. depinstall automattically creates a Dstate for each state passed to it as well as a state0 (optional). This is OK since they dissappear if unused. */ #define FORALL(state,dstate) \ for (state = init_forderiv(dstate); state; state = next_forderiv()) /* This returns all states of lower order than dstate in the order of base state first. Will install PRIME if necessary. */ static Symbol *forderiv; /* base state */ static char base_units[50]; /*base state units */ static int indx, maxindx; /* current indx, and indx of dstate */ static Symbol * init_forderiv(prime) Symbol *prime; { char name[100]; double d1, d2; assert(prime->type == PRIME); /*extract maxindx and basename*/ if (isdigit(prime->name[1])) { /* higher than 1 */ if(sscanf(prime->name + 1, "%d%s", &maxindx, name) != 2) { diag("internal error in init_forderiv in init.c", (char *)0); } }else{ maxindx = 1; Strcpy(name, prime->name + 1); } forderiv = lookup(name); if (!forderiv || !(forderiv->subtype & STAT)) { diag(name, " must be declared as a state variable"); } if (forderiv->araydim != prime->araydim) { Sprintf(buf, "%s and %s have different dimensions", forderiv->name, prime->name); diag(buf, (char *)0); } indx = 0; decode_ustr(forderiv, &d1, &d2, base_units); return forderiv; } static char *name_forderiv(i) int i; { static char name[100]; assert(i > 0 && forderiv); if (i > 1) { Sprintf(name, "D%d%s", i, forderiv->name); }else{ Sprintf(name, "D%s", forderiv->name); } return name; } /* Scop can handle 's so we put the prime style names into the .var file. We make use of the tools here to reconstruct the original prime name. */ char *reprime(sym) Symbol *sym; { static char name[100]; int i; char *cp; if (sym->type != PRIME) { Strcpy(name, sym->name); return name; } IGNORE(init_forderiv(sym)); Strcpy(name, forderiv->name); cp = name + strlen(name); for (i=0; i= maxindx) { return SYM0; } name = name_forderiv(indx); if((s = lookup(name)) == SYM0) { s = install(name, PRIME); Sprintf(units, "%s/%s^%d", base_units, STR(indeplist->prev), indx); depinstall(1, s, forderiv->araydim, "0", "1", units, ITEM0, 1, ""); s->usage |= DEP; } if (s->araydim != forderiv->araydim) { diag(s->name, " must have same dimension as associated state"); } if (!(s->subtype & STAT)) {/* Dstate changes to state */ Sprintf(units, "%s/%s^%d", base_units, STR(indeplist->prev), indx); s->subtype &= ~DEP; depinstall(1, s, forderiv->araydim, "0", "1", units, ITEM0, 1, ""); depinstall(1, s, forderiv->araydim, "0", "1", units, ITEM0, 1, ""); s->usage |= DEP; } return s; } /* mixed derivative and nonlinear equations */ /* Implementation: The main requirement is to distinguish between the states which have derivative specifications and the states which are solved for by the nonlinear equations. We do this by having the left hand side derivative saved in a list instead of marking the variables in the used field. See deriv_used(). States seen in the nonlinear equations are marked as usual. To leave only nonlinear states marked we then cast out any lesser state which is marked. (eg if y''=.. then y and y' cannot be states of the nonlinear equation). The former version also made use of state->used = -1 for match purposes. We replace this usage with a list of states of the derivatives. This means that the derivative block with respect to derivative equations no longer uses the used field. To avoid copying the block we (albeit resulting is somewhat poorer efficiency) we allow the block to call newton and pass itself as an argument. A flag tells the block if its call was by newton or by an integrator. My guess is this will still work with match, sens, and array states. */ /* derivative equations (and possibly some nonlinear equations) solved with an implicit method */ /* Implementation: Things are starting to get a little bit out of conceptual control. We make use of the mixed case, except that the number of nonlinear equations may be 0. The substantive change is that now the number of equations is the sum of the derivatives and the nonlinears and the extra equations added into the block are of the form dlist2[++_counte] = Dstate - (state - statesave1[0])/dt; The administrative needs are that newton is called with the total number of equations and that we can match state and statesave. Notice that we already have two sets of slists floating around and one dlist, currently they are the slist and dlist for the derivative state and state' and the slist for the nonlinear states (the corresponding dlist is just the rhs of the equations). Clearly, statesave should be associated with the derivative slist and will be in that order, then the slist for newton will be expanded by not resetting the used field. The biggest conceptual problem is how to generate the code at the time we handle the SOLVE since the actual numbers for the declarations of the newton slists depend on the method. Here, we assume a flag, deriv_implicit, which tells us which code to generate. Whether this means that we must look through the .mod file for all the SOLVE statements or whether all this stuff is saved for calling from the solve handler as in the kinetic block is not specified yet. For now, we demand that the SOLVE statement be seen first if it invokes the derivimplicit method. Otherwise modl generates an error message. */ void add_deriv_imp_list(name) char *name; { if (!deriv_imp_list) { deriv_imp_list = newlist(); } Lappendstr(deriv_imp_list, name); } void add_deriv_imp_really(name) char *name; { if (!deriv_imp_really) { deriv_imp_really = newlist(); } Lappendstr(deriv_imp_really, name); } static List *deriv_used_list; /* left hand side derivatives of diffeqs */ static List *deriv_state_list; /* states of the derivative equations */ void deriv_used(s, q1, q2) /* q1, q2 are begin and end tokens for expression */ Symbol *s; Item* q1, *q2; { if (!deriv_used_list) { deriv_used_list = newlist(); deriv_state_list = newlist(); } Lappendsym(deriv_used_list, s); #if CVODE if (!cvode_diffeq_list) { cvode_diffeq_list = newlist(); } lappendsym(cvode_diffeq_list, s); lappenditem(cvode_diffeq_list, q1); lappenditem(cvode_diffeq_list, q2); #endif } static int matchused = 0; /* set when MATCH seen */ /* args are --- derivblk: DERIVATIVE NAME stmtlist '}' */ void massagederiv(q1, q2, q3, q4, sensused) Item *q1, *q2, *q3, *q4; int sensused; { int count = 0, deriv_implicit, deriv_implicit_really, solve_seen; char units[50]; Item *qs, *q, *mixed_eqns(); Symbol *s, *derfun, *state; /* to allow verification that definition after SOLVE */ if (!massage_list_) { massage_list_ = newlist(); } Lappendsym(massage_list_, SYM(q2)); derfun = SYM(q2); /* check if we are to translate using derivimplicit method */ deriv_implicit = 0; if (deriv_imp_list) ITERATE(q, deriv_imp_list) { if (strcmp(derfun->name, STR(q)) == 0) { deriv_implicit = 1; break; } } deriv_implicit_really = 0; if (deriv_imp_really) ITERATE(q, deriv_imp_really) { if (strcmp(derfun->name, STR(q)) == 0) { deriv_implicit_really = 1; break; } } /* all this junk is still in the intoken list */ Sprintf(buf, "static inline int %s(_threadargsproto_);\n", SYM(q2)->name); if (deriv_implicit_really == 1) { Sprintf(buf, "struct %s%s {\n int operator()(_threadargsproto_) const;\n};\n", SYM(q2)->name, suffix); } Linsertstr(procfunc, buf); if (deriv_implicit_really == 1) { replacstr(q1, "\nint"); q = insertstr(q3, "() {_reset=0;\n"); }else{ replacstr(q1, "\nstatic int"); q = insertstr(q3, "() {_reset=0;\n"); } vectorize_substitute(q, "::operator()(_threadargsproto_) const {\n int _reset=0;\n int error = 0;\n"); if (derfun->subtype & DERF && derfun->u.i) { diag("DERIVATIVE merging not implemented", (char *)0); } numlist++; derfun->u.i = numlist; derfun->subtype |= DERF; if (!deriv_used_list) { diag("No derivative equations in DERIVATIVE block", (char*)0); } count = 0; ITERATE(qs, deriv_used_list) { s = SYM(qs); FORALL(state, s) { count++; } } Sprintf(buf, "\n" " _slist%d = (int*)malloc(sizeof(int)*%d);\n" " _dlist%d = (int*)malloc(sizeof(int)*%d);\n" , numlist, count, numlist, count ); Lappendstr(initlist, buf); count = 0; ITERATE(qs, deriv_used_list) { s = SYM(qs); if (!(s->subtype & DEP) && !(s->subtype & STAT)) { IGNORE(init_forderiv(s)); Sprintf(units, "%s/%s^%d", base_units, STR(indeplist->prev), maxindx); depinstall(0, s, s->araydim, "0", "1", units, ITEM0, 0, ""); } /* high order: make sure no lesser order is marked, and all lesser orders exist as STAT */ FORALL(state, s) { if (state->type == PRIME) { ITERATE(q, deriv_used_list) if (state == SYM(q)) { diag(state->name, ": Since higher derivative is being used, this state \ is not allowed on the left hand side."); } } Lappendsym(deriv_state_list, state); if (sensused) { add_sens_statelist(state); state->varnum = count; } #if CVODE slist_data(state, count, numlist); #endif if (s->subtype & ARRAY) { int dim = s->araydim; Sprintf(buf, "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = (%s + _i) - _p;" ,dim, numlist , count, state->name); Lappendstr(initlist, buf); Sprintf(buf, " _dlist%d[%d+_i] = (%s + _i) - _p;}\n" , numlist, count, name_forderiv(indx + 1)); Lappendstr(initlist, buf); count += dim; }else{ Sprintf(buf, "_slist%d[%d] = &(%s) - _p;", numlist, count, state->name); Lappendstr(initlist, buf); Sprintf(buf, " _dlist%d[%d] = &(%s) - _p;\n", numlist, count, name_forderiv(indx + 1)); Lappendstr(initlist, buf); count++; } } } Sprintf(buf, "#pragma acc enter data copyin(_slist%d[0:%d])\n" " #pragma acc enter data copyin(_dlist%d[0:%d])\n\n" , numlist, count, numlist, count); Lappendstr(initlist, buf); if (count == 0) { diag("DERIVATIVE contains no derivatives", (char *)0); } derfun->used = count; Sprintf(buf, ", _slist%d[0:%d], _dlist%d[0:%d]", numlist, count, numlist, count); Lappendstr(acc_present_list, buf); Sprintf(buf, "\n#define _slist%d _slist%d%s\n" "int* _slist%d;\n" "#pragma acc declare create(_slist%d)\n" "\n#define _dlist%d _dlist%d%s\n" "int* _dlist%d;\n" "#pragma acc declare create(_dlist%d)\n" , numlist, numlist, suffix, numlist, numlist , numlist, numlist, suffix, numlist, numlist ); Linsertstr(procfunc, buf); #if CVODE Lappendstr(procfunc, "\n/*CVODE*/\n"); Sprintf(buf, "static int _ode_spec%d", numlist); Lappendstr(procfunc, buf); {Item* qq = procfunc->prev; copyitems(q1->next, q4, procfunc->prev); vectorize_substitute(qq->next, "(_threadargsproto_) {int _reset = 0;"); vectorize_scan_for_func(qq->next, procfunc); } lappendstr(procfunc, "return _reset;\n}\n"); /* don't emit _ode_matsol if the user has defined cvodematsol */ if (!lookup("cvodematsol")) { Item* qq; Item* qextra = q1->next->next->next->next; Sprintf(buf, "static int _ode_matsol%d", numlist); Lappendstr(procfunc, buf); vectorize_substitute(lappendstr(procfunc, "() {\n"), "(_threadargsproto_) {\n"); qq = procfunc->next; cvode_cnexp_possible = 1; ITERATE(q, cvode_diffeq_list) { Symbol* s; Item* q1, *q2; s = SYM(q); q = q->next; q1=ITM(q); q = q->next; q2 = ITM(q); #if 1 while (qextra != q1) { /* must first have any intervening statements */ switch (qextra->itemtype) { case STRING: Lappendstr(procfunc, STR(qextra)); break; case SYMBOL: Lappendsym(procfunc, SYM(qextra)); break; } qextra = qextra->next; } #endif cvode_diffeq(s, q1, q2); qextra = q2->next; } Lappendstr(procfunc, ";\n return 0;\n}\n"); vectorize_scan_for_func(qq, procfunc); } Lappendstr(procfunc, "/*END CVODE*/\n"); if (cvode_cnexp_solve && cvode_cnexp_success(q1, q4)) { freelist(&deriv_used_list); freelist(&deriv_state_list); return; } #endif if (deriv_implicit) { Sprintf(buf, "static double _savstate%d[%d], *_temp%d = _savstate%d;\n", numlist, count*(1 + 2*sens_parm), numlist, numlist); q = linsertstr(procfunc, buf); vectorize_substitute(q, ""); }else{ Sprintf(buf, "static double *_temp%d;\n", numlist); Linsertstr(procfunc, buf); } movelist(q1, q4, procfunc); Lappendstr(procfunc, "return _reset;}\n"); if (sensused) sensmassage(DERIVATIVE, q2, numlist); /*among other things the name of q2 is changed. ie a new item */ if (matchused) { matchmassage(count); } /* reset used field for any states that may appear in nonlinear equations which should not be solved for. */ ITERATE(q, deriv_used_list) { SYM(q)->used = 0; } if (deriv_implicit) { Symbol *sp; ITERATE(q, deriv_state_list) { SYM(q)->used = 1; } Sprintf(buf, "{int _id; for(_id=0; _id < %d; _id++) {\n\ if (_deriv%d_advance) {\n", count, numlist); Insertstr(q4, buf); sp = install("D", STRING); sp->araydim = count; /*this breaks SENS*/ q = insertsym(q4, sp); eqnqueue(q); Sprintf(buf, "_p[_dlist%d[_id]*_STRIDE] - (_p[_slist%d[_id]*_STRIDE] - _savstate%d[_id*_STRIDE])/d%s;\n", numlist, numlist, numlist, indepsym->name); Insertstr(q4, buf); Sprintf(buf, "}else{\n_dlist%d[(++_counte)*_STRIDE] = _p[_slist%d[_id]*_STRIDE] - _savstate%d[_id*_STRIDE];}}}\n", numlist+1, numlist, numlist); Insertstr(q4, buf); }else{ ITERATE(q, deriv_state_list) { SYM(q)->used = 0; } } /* if there are also nonlinear equations, put in the newton call, create the proper lists and fill in the left hand side of each equation. */ q = mixed_eqns(q2, q3, q4); /* numlist now incremented */ if (deriv_implicit) { Sprintf(buf, "{int _id; for(_id=0; _id < %d; _id++) { _savstate%d[_id*_STRIDE] = _p[_slist%d[_id]*_STRIDE];}}\n", count, derfun->u.i, derfun->u.i); Insertstr(q, buf); } freelist(&deriv_used_list); freelist(&deriv_state_list); } static List *match_init; /* list of states for which initial values are known. */ List *match_bound; /* list of triples or quadruples. First is the state symbol. Second is a string giving the matchtime expression. Third is a string giving the matchtarget expression Fourth is the loop index string if the state is an array*/ /* if non null then cout.c will put proper call at end of initmodel() */ /* note that the number of states in match_init plus the number of states in match_bound must be equal to the number of differential equations */ /* we limit ourselves to one matched boundary problem per model */ void matchinitial(q1) /* name */ Item *q1; { /* must be of form state0. Later we can check if state' is in fact used. Save the state symbol in the initialvalue matchlist */ Symbol *s, *state; s = SYM(q1); if ((s->subtype & (PARM | INDEP)) || !(s->subtype)) { /* possibly used before declared */ if (s->name[strlen(s->name) - 1] == '0') { Strcpy(buf, s->name); buf[strlen(buf) - 1] = '\0'; state = lookup(buf); if((state && (state->subtype & STAT)) || (state->type == PRIME)) { Lappendsym(match_init, state); return; } } } diag(s->name, " must be an initial state parameter"); return; } void matchbound(q1, q2, q3, q4, q5, sindex) /* q1name q2'(' q3')' '=' q4exprq5 */ Item *q1, *q2, *q3, *q4, *q5; Symbol *sindex; { /* q1 must be a state */ Symbol *state; Item *q; List *l; state = SYM(q1); if (!(state->subtype & STAT) && state->type != PRIME) { diag(state->name, " is not a state"); } if ((state->subtype & ARRAY) && !sindex) { diag(state->name, " must have an index for the implicit loop"); } if (!(state->subtype & ARRAY) && sindex) { diag(state->name, " is not an array"); } Lappendsym(match_bound, state); q = lappendsym(match_bound, SYM0); l = newlist(); movelist(q2, q3, l); LST(q) = l; q = lappendsym(match_bound, SYM0); l = newlist(); movelist(q4, q5, l); LST(q) = l; if (sindex) { Lappendstr(match_bound, sindex->name); } } void checkmatch(blocktype) int blocktype; { if (blocktype != DERIVATIVE) { diag("MATCH block can only be in DERIVATIVE block", (char *)0); } matchused = 1; /*communicate with massagederiv*/ if (match_bound || match_init) { diag("Only one MATCH block allowed", (char *)0); } if (!indepsym) { diag("INDEPENDENT variable must be declared before MATCH", " statement"); } match_bound = newlist(); match_init = newlist(); } void matchmassage(nderiv) int nderiv; { int count, nunknown, j; Item *q, *q1, *setup; Symbol *s; List *tmatch, *vmatch; char *imatch; matchused = 0; /* we have a list of states at which the initial values are known and a list of information about state(time) = match with implicit loop index if array. check that the total number of conditions = nderiv. the number of unknown initial conditions is the complement of the states which have known initial conditions ( the number of states in the match_bound list. Note that the complement of match_init states is NOT the list of states in match_bound. We create 1) array of doubles which will receive the values of the found initial conditions. (_found_init) 2) array of doubles which receives the match times 3) array of doubles which receives the match values 4) array of state pointers(state_match). we solve *statematch(matchtime) = matchvalue 5) array of state pointers(state_get). We initialize with *state_get = _found_init 6) since 2, 3, 4 must be sorted according to match times we create pointer arrays to 2 and 3 and pass those. 7) Spec of shoot requires the passing of pointer array to found_init. At this time I don't know how this can be restarted. Initmodel() calls _initmatch() which 1) if first=1 then sets first=0 sets up match times, match values, initializes _found_init, calls shoot(), calls initmodel(), sets first = 1 and exits. 2) if first=0 then put _found_init into states and exit. Call to _initmatch must be the last thing done in initmodel() in case the user desires to give good starting initial values to help shoot(). */ count = 0; ITERATE(q, match_init) { /* these initializations are done automatically by initmodel(), so just remove the state from the deriv_state_list */ s = SYM(q); ITERATE(q1, deriv_state_list) { if (SYM(q1) == s) { delete(q1); break; } } if (!(s->subtype & STAT)) { diag(s->name, " is not a state"); } if (s->subtype & ARRAY) { count += s->araydim; }else{ count++; } } nunknown = nderiv - count; if (nunknown <= 0) { diag("Nothing to match", (char *)0); } /* the ones that are still marked are the ones to solve for */ /* add the boilerplate for _initmatch and save the location where model specific info goes. */ Lappendstr(procfunc, "\n_init_match(_save) double _save;{ int _i;\nif (_match_recurse) {_match_recurse = 0;\n"); Sprintf(buf, "for (_i=0; _i<%d; _i++) _found_init[_i] = _p[_state_get[_i]];\n", nunknown); setup = lappendstr(procfunc, buf); Sprintf(buf, "error=shoot(%d, &(%s) - _p, _pmatch_time, _pmatch_value, _state_match,\ _found_init, _p, &(d%s));\n if(error){abort_run(error);}; %s = _save;", nunknown, indepsym->name, indepsym->name, indepsym->name); /*deltaindep may not be declared yet */ Lappendstr(procfunc, buf); Lappendstr(procfunc,"\n initmodel(_p); _match_recurse = 1;\n}\n"); Sprintf(buf, "for (_i=0; _i<%d; _i++) _p[_state_get[_i]] = _found_init[_i];", nunknown); Lappendstr(procfunc, buf); Lappendstr(procfunc, "\n}\n\n"); /* construct _state_get from the marked states */ j = 0; ITERATE(q, deriv_state_list) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "for (_i=0; _i<%d; _i++) {_state_get[%d+_i] = (%s + _i) - _p;}\n", s->araydim, j, s->name); j += s->araydim; } else { Sprintf(buf, "_state_get[%d] = &(%s) - _p;\n", j, s->name); j++; } Lappendstr(initlist, buf); } /* declare the arrays */ Sprintf(buf, "static int _state_get[%d], _state_match[%d];\n\ static double _match_time[%d], _match_value[%d], _found_init[%d];\n", nunknown, nunknown, nunknown, nunknown, nunknown); Linsertstr(procfunc, buf); Sprintf(buf, "static double *_pmatch_time[%d], *_pmatch_value[%d];\n", nunknown, nunknown); Linsertstr(procfunc, buf); /* create the _state_match stuff */ j = 0; ITERATE(q, match_bound) { s = SYM(q); if (!(s->subtype & STAT)) { diag(s->name, " is not a state"); } tmatch = LST(q = q->next); vmatch = LST(q = q->next); if (s->subtype & ARRAY) { imatch = STR(q = q->next); Sprintf(buf, "for (_i=0; _i<%d; _i++) {_state_match[%d+_i] = (%s + _i) - _p;}\n", s->araydim, j, s->name); Lappendstr(initlist, buf); Sprintf(buf, "{int %s; for (%s=0; %s<%d; %s++) {\n", imatch, imatch, imatch, s->araydim, imatch); Insertstr(setup, buf); Sprintf(buf, "_match_time[%s + %d] = ", imatch, j); Insertstr(setup, buf); copylist(tmatch, setup); Sprintf(buf, ";\n _match_value[%s + %d] = ", imatch, j); Insertstr(setup, buf); copylist(vmatch, setup); Insertstr(setup, ";\n}}\n"); j += s->araydim; count += s->araydim; }else{ Sprintf(buf, "_state_match[%d] = &(%s) - _p;\n", j, s->name); Lappendstr(initlist, buf); Sprintf(buf, "_match_time[%d] = ", j); Insertstr(setup, buf); copylist(tmatch, setup); Sprintf(buf, ";\n _match_value[%d] = ", j); Insertstr(setup, buf); copylist(vmatch, setup); Insertstr(setup, ";\n"); j++; count++; } } /* set up the trivial pointer arrays */ Sprintf(buf, "for(_i=0; _i<%d; _i++) { _pmatch_time[_i] = _match_time + _i;\n", nunknown); Lappendstr(initlist, buf); Lappendstr(initlist, "_pmatch_value[_i] = _match_value + _i;\n }\n"); if (count != nderiv) { Sprintf(buf, "%d equations != %d MATCH specs", nderiv, count); diag(buf, (char *)0); } } static void copylist(l, i) /* copy list l before item i */ List *l; Item *i; { Item *q; ITERATE(q, l) { switch(q->itemtype) { case STRING: Insertstr(i, STR(q)); break; case SYMBOL: Insertsym(i, SYM(q)); break; default: /*SUPPRESS 622*/ assert(0); } } } void copyitems(q1, q2, qdest) /* copy items before item */ Item* q1, *q2, *qdest; { Item* q; for (q = q2; q != q1; q = q->prev) { switch(q->itemtype) { case STRING: case VERBATIM: Linsertstr(qdest, STR(q)); break; case SYMBOL: Linsertsym(qdest, SYM(q)); break; default: /*SUPPRESS 622*/ assert(0); } } } #if CVODE static int cvode_linear_diffeq(ds, s, qbegin, qend) Symbol*ds, *s; Item* qbegin, *qend; { char* c; List* tlst; Item* q; tlst = newlist(); for (q = qbegin; q != qend->next; q = q->next) { switch (q->itemtype) { case SYMBOL: lappendsym(tlst, SYM(q)); break; case STRING: lappendstr(tlst, STR(q)); break; default: cvode_cnexp_possible = 0; return 0; } } cvode_parse(s, tlst); freelist(&tlst); c = cvode_deriv(); if (!cvode_eqn) { cvode_eqn = newlist(); } lappendsym(cvode_eqn, s); lappendstr(cvode_eqn, cvode_deriv()); lappendstr(cvode_eqn, cvode_eqnrhs()); if (c) { lappendstr(procfunc, c); lappendstr(procfunc, "))"); return 1; } cvode_cnexp_possible = 0; return 0; } /* DState symbol, begin, and end of expression */ static void cvode_diffeq(ds, qbegin, qend) Symbol* ds; Item* qbegin, *qend; { /* try first the assumption of linear. If not, then use numerical diff*/ Symbol* s; Item* q; /* get state symbol */ sscanf(ds->name, "D%s", buf); s = lookup(buf); assert(s); /* ds/(1. - dt*( */ Lappendsym(procfunc, ds); Lappendstr(procfunc, " / (1. - dt*("); if (cvode_linear_diffeq(ds, s, qbegin, qend)) { return; } /* ((expr(s+.001))-(expr))/.001; */ Lappendstr(procfunc, "(("); for (q = qbegin; q != qend->next; q = q->next) { switch(q->itemtype) { case STRING: Lappendstr(procfunc, STR(q)); break; case SYMBOL: if (SYM(q) == s) { Lappendstr(procfunc, "("); Lappendsym(procfunc, s); Lappendstr(procfunc, " + .001)"); }else{ Lappendsym(procfunc, SYM(q)); } break; default: assert(0); } } Lappendstr(procfunc, ") - ("); for (q = qbegin; q != qend->next; q = q->next) { switch(q->itemtype) { case STRING: Lappendstr(procfunc, STR(q)); break; case SYMBOL: Lappendsym(procfunc, SYM(q)); break; default: assert(0); } } Lappendstr(procfunc, " )) / .001 ))"); } /* the cnexp method was requested but the symbol in the solve queue was changed to derivimplicit and cvode_cnexp_solve holds a pointer to the solvq item (1st of three). The 0=f(state) equations have already been solved and the rhs for each has been saved. So we know if the translation is possible. */ int cvode_cnexp_success(q1, q2) Item* q1, *q2; { Item* q, *q3, *q4, *qeq; if ( cvode_cnexp_possible) { /* convert Method to nil and the type of the block to PROCEDURE */ SYM(cvode_cnexp_solve->next)->name = stralloc("cnexp", 0); delete(deriv_imp_list->next); /* replace the Dstate = f(state) equations */ qeq = cvode_eqn->next; ITERATE(q, cvode_diffeq_list) { Symbol* s; Item* q1, *q2; char* a, *b; s = SYM(qeq); qeq = qeq->next; a = STR(qeq); qeq = qeq->next; b = STR(qeq); qeq = qeq->next; q = q->next; q1=ITM(q); q = q->next; q2 = ITM(q); if (strcmp(a, "0.0") == 0) { assert(b[strlen(b) - 9] == '/'); b[strlen(b) - 9] = '\0'; sprintf(buf," %s = %s - dt*(%s)", s->name, s->name, b); }else{ sprintf(buf," %s = %s + (1. - exp(dt*(%s)))*(%s - %s)", s->name, s->name, a, b, s->name ); } insertstr(q2->next, buf); q2 = q2->next; for(q3=q1->prev->prev; q3 != q2; q3 = q4) { q4 = q3->next; delete(q3); } } lappendstr(procfunc, "static int"); { Item* qq = procfunc->prev; copyitems(q1, q2, procfunc->prev); /* more or less redundant with massagederiv */ vectorize_substitute(qq->next->next, "(_threadargsproto_) {"); vectorize_scan_for_func(qq->next->next, procfunc); } lappendstr(procfunc, " return 0;\n}\n"); return 1; } fprintf(stderr, "Could not translate using cnexp method; using derivimplicit\n"); return 0; } #endif mod2c-8.2.2/src/mod2c_core/difeqdef.h000077500000000000000000000023011425457616700172720ustar00rootroot00000000000000 #define yymaxdepth difeq_yymaxdepth #define yyparse difeq_yyparse #define yylex difeq_yylex #define yyerror difeq_yyerror #define yylval difeq_yylval #define yychar difeq_yychar #define yydebug difeq_yydebug #define yypact difeq_yypact #define yyr1 difeq_yyr1 #define yyr2 difeq_yyr2 #define yydef difeq_yydef #define yychk difeq_yychk #define yypgo difeq_yypgo #define yyact difeq_yyact #define yyexca difeq_yyexca #define yyerrflag difeq_yyerrflag #define yynerrs difeq_yynerrs #define yyps difeq_yyps #define yypv difeq_yypv #define yys difeq_yys #define yy_yys difeq_yyyys #define yystate difeq_yystate #define yytmp difeq_yytmp #define yyv difeq_yyv #define yy_yyv difeq_yyyyv #define yyval difeq_yyval #define yylloc difeq_yylloc #define yyreds difeq_yyreds #define yytoks difeq_yytoks #define yylhs difeq_yyyylhs #define yylen difeq_yyyylen #define yydefred difeq_yyyydefred #define yydgoto difeq_yyyydgoto #define yysindex difeq_yyyysindex #define yyrindex difeq_yyyyrindex #define yygindex difeq_yyyygindex #define yytable difeq_yyyytable #define yycheck difeq_yyyycheck mod2c-8.2.2/src/mod2c_core/diffeq.y000077500000000000000000000170351425457616700170140ustar00rootroot00000000000000%{ /* symbolically differentiate an expression with respect to a state and also transform an expression linear in the state into the form a*state + b The only thing that makes this less than elegant is dealing with 0.0 */ #include "nmodlconf.h" #include #include "modl.h" #include "difeqdef.h" /* every yy gets changed to diffeq_yy before compiling */ static int yylex(), yyparse(); static void yyerror(); static int d_invalid, eq_invalid; static char lbuf[4][1000]; static Item* qexpr; /* yylex finds tokens here;*/ static Symbol* state; static List* result; #define b1 sprintf(lbuf[0], #define b2 sprintf(lbuf[1], #define b3 sprintf(lbuf[2], #define b4 sprintf(lbuf[3], static void replace(), initbuf(), free4(); static int zero(); static char *expr(), *de(), *a(), *b(); static List* list4(); %} %union { char* cp; List* list; /* expression, d(expression)/dstate, a*state, b */ } %token ATOM %type e arglist arg %left '+' '-' %left '*' '/' %left UNARYMINUS %% top: {d_invalid = 0; eq_invalid = 0; } e {result = $2;} ; e: ATOM {$$ = $1;} | '(' e ')' { $$ = $2; initbuf(); b1 "( %s )", expr($$)); if (!zero(de($$))) {b2 "( %s )", de($$));} if (!zero(a($$))) {b3 "( %s )", a($$));} if (!zero(b($$))) {b4 "( %s )", b($$));} replace($$); } | ATOM '(' arglist ')' { $$ = $3; initbuf(); b1 "%s ( %s )", expr($1), expr($$)); {b4 "%s ( %s )", expr($1), expr($$));} free4($1); replace($$); } | '-' e %prec UNARYMINUS { $$ = $2; initbuf(); b1 "- %s", expr($$)); if (!zero(de($$))) {b2 "- %s", de($$));} if (!zero(a($$))) {b3 "- %s", a($$));} if (!zero(b($$))) {b4 "- %s", b($$));} replace($$); } | e '+' e { $$ = $1; initbuf(); b1 "%s + %s", expr($1), expr($3)); if (!zero(de($1)) && !zero(de($3))) {b2 "%s + %s", de($1), de($3)); }else if (!zero(de($1))) {b2 "%s", de($1)); }else if (!zero(de($3))) {b2 "%s", de($3));} if (!zero(a($1)) && !zero(a($3))) {b3 "%s + %s", a($1), a($3)); }else if (!zero(a($1))) {b3 "%s", a($1)); }else if (!zero(a($3))) {b3 "%s", a($3));} if (!zero(b($1)) && !zero(b($3))) {b4 "%s + %s", b($1), b($3)); }else if (!zero(b($1))) {b4 "%s", b($1)); }else if (!zero(b($3))) {b4 "%s", b($3));} free4($3); replace($$); } | e '-' e { $$ = $1; initbuf(); b1 "%s - %s", expr($1), expr($3)); if (!zero(de($1)) && !zero(de($3))) {b2 "%s - %s", de($1), de($3)); }else if (!zero(de($1))) {b2 "%s", de($1)); }else if (!zero(de($3))) {b2 "( - %s )", de($3));} if (!zero(a($1)) && !zero(a($3))) {b3 "%s - %s", a($1), a($3)); }else if (!zero(a($1))) {b3 "%s", a($1)); }else if (!zero(a($3))) {b3 "( - %s)", a($3));} if (!zero(b($1)) && !zero(b($3))) {b4 "%s - %s", b($1), b($3)); }else if (!zero(b($1))) {b4 "%s", b($1)); }else if (!zero(b($3))) {b4 "( - %s )", b($3));} free4($3); replace($$); } | e '*' e { $$ = $1; initbuf(); b1 "%s * %s", expr($1), expr($3)); if (!zero(de($1)) && !zero(de($3))) { b2 "((%s)*(%s) + (%s)*(%s))", de($1), expr($3), expr($1), de($3)); }else if (!zero(de($1))) {b2 "(%s)*(%s)", de($1), expr($3)); }else if (!zero(de($3))) {b2 "(%s)*(%s)", expr($1), de($3));} if (!zero(a($1)) && !zero(a($3))) {eq_invalid = 1; }else if (!zero(a($1))) { if (!zero(b($3))) {b3 "(%s)*(%s)", a($1),b($3));} }else if (!zero(a($3))) { if (!zero(b($1))) {b3 "(%s)*(%s)", b($1),a($3));}} if (!zero(b($1)) && !zero(b($3))) { b4 "(%s)*(%s)", b($1), b($3));} free4($3); replace($$); } | e '/' e { $$ = $1; initbuf(); b1 "%s / %s", expr($1), expr($3)); if (!zero(de($3))) { d_invalid = 1; }else if (!zero(de($1))) { b2 "( %s ) / %s", de($1), expr($3));} if (!zero(a($3))) { eq_invalid = 1; }else if (!zero(a($1))) { b3 "( %s ) / %s", a($1), expr($3));} if (!zero(b($1))) { b4 "( %s ) / %s", b($1), expr($3));} free4($3); replace($$); } ; arglist: /*nothing*/ { $$ = list4("", "0.0", "0.0", ""); } | arg { $$ = $1; } | arglist arg { $$ = $2; b1 "%s %s", expr($1), expr($2)); b4 "%s %s", expr($1), expr($2)); free4($1); replace($$); } | arglist ',' arg { $$ = $3; b1 "%s , %s", expr($1), expr($3)); b4 "%s , %s", expr($1), expr($3)); free4($1); replace($$); } ; arg: e { $$ = $1; initbuf(); b1 "%s", expr($1)); if (!zero(de($$))) { d_invalid = 1; } if (!zero(de($$))) { eq_invalid = 1; } {b4 "%s", expr($$));} } ; %% static int zero(cp) char* cp; { return (strcmp(cp, "0.0") == 0) ? 1 : 0; } static char* expr(lst) List* lst; { Item* q = lst->next; return STR(q); } static char* de(lst) List* lst; { Item* q = lst->next->next; return STR(q); } static char* a(lst) List* lst; { Item* q = lst->next->next->next; return STR(q); } static char* b(lst) List* lst; { Item* q = lst->next->next->next->next; return STR(q); } static void replace(lst) List* lst; { int i; Item* q = lst->next; for (i=0; i < 4; ++i) { free(STR(q)); replacstr(q, lbuf[i]); q = q->next; } #if 0 fprintf(stderr, "replace expr|%s| de|%s| a|%s| b|%s|\n", lbuf[0], lbuf[1], lbuf[2], lbuf[3]); #endif } static void initbuf() { int i; for (i=0; i < 4; ++i) { strcpy(lbuf[i], "0.0"); } } static List* list4(s1, s2, s3, s4) char *s1, *s2, *s3, *s4; { List* lst = newlist(); lappendstr(lst, s1); lappendstr(lst, s2); lappendstr(lst, s3); lappendstr(lst, s4); return lst; } static void free4(lst) List* lst; { Item* q; List* ls = lst; ITERATE(q, lst) { free(STR(q)); } freelist(&ls); } static void yyerror(s) char* s; { assert(0); } static void fullname(buf) char* buf; { /* handle case of name [...] with qexpr pointing to final item */ Item* q = qexpr; strcpy(buf, SYM(q)->name); if (q->next->itemtype == SYMBOL && strcmp(SYM(q->next)->name, "[") == 0) { q = q->next; strcat(buf, "["); for (;;) { q = q->next; if (q->itemtype == SYMBOL) { strcat(buf, SYM(q)->name); if (strcmp(SYM(q)->name, "]") == 0) { break; } }else if (q->itemtype == ITEM || q->itemtype == LIST) { assert(0); }else{ /* had better be a STRING */ strcat(buf, STR(q)); } } } qexpr = q; } static int yylex() { Symbol* s; char buf[256]; int rval = 0; if (qexpr->itemtype == 0) { return 0; } switch (qexpr->itemtype) { case SYMBOL: s = SYM(qexpr); if (s == state) { fullname(buf); yylval.list = list4(buf, "1.0", "1.0", "0.0"); rval = ATOM; }else{ switch (s->name[0]) { case '+': case '-': case '*': case '/': case '(': case ')': case ',': rval = s->name[0]; break; default: fullname(buf); yylval.list = list4(buf, "0.0", "0.0", buf); rval = ATOM; break; } } break; default: /* had better be a STRING */ if (strcmp(STR(qexpr), "") == 0) { qexpr = qexpr->next; return yylex(); } yylval.list = list4(STR(qexpr), "0.0", "0.0", STR(qexpr)); rval = ATOM; break; } #if 0 if (rval == ATOM) { fprintf(stderr, "expr|%s| de|%s| a|%s| b|%s|\n", expr(yylval.list), de(yylval.list), a(yylval.list), b(yylval.list)); }else{ fprintf(stderr, "|%s|\n", SYM(qexpr)->name); } #endif qexpr = qexpr->next; return rval; } /*----------- interface to outside world -------------*/ void cvode_parse(s, e) Symbol* s; List* e; { state = s; qexpr = e->next; yyparse(); #if 0 fprintf(stderr, "cvode_parse d_invalid=%d eq_invalid=%d\nexpr|%s|\nde|%s|\na|%s|\nb|%s|\n", d_invalid, eq_invalid, expr(result), de(result), a(result), b(result)); #endif b4 "- ( %s ) / ( %s )", b(result), a(result)); replacstr(result->prev, lbuf[3]); } char* cvode_deriv() { if (result && !d_invalid) { return de(result); }else{ return (char*)0; } } char* cvode_eqnrhs() { if (result && !eq_invalid) { return b(result); }else{ return (char*)0; } } mod2c-8.2.2/src/mod2c_core/discrete.c000066400000000000000000000131461425457616700173260ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/discrete.c,v 4.1 1997/08/30 20:45:19 hines Exp */ /* discrete.c,v * Revision 4.1 1997/08/30 20:45:19 hines * cvs problem with branches. Latest nmodl stuff should now be a top level * * Revision 4.0.1.1 1997/08/08 17:23:42 hines * nocmodl version 4.0.1 * * Revision 4.0 1997/08/08 17:06:07 hines * proper nocmodl version number * * Revision 1.1.1.1 1994/10/12 17:21:35 hines * NEURON 3.0 distribution * * Revision 9.5 90/07/18 07:59:36 hines * define for arrays now (p + n) instead of &p[n]. This allows the c file * to have arrays that look like a[i] instead of *(a + i). * * Revision 8.1 90/01/03 16:13:01 mlh * discrete array variables had their for loops switched. * * Revision 8.0 89/09/22 17:26:05 nfh * Freezing * * Revision 7.0 89/08/30 13:31:32 nfh * Rev 7 is now Experimental; Rev 6 is Testing * * Revision 6.0 89/08/14 16:26:16 nfh * Rev 6.0 is latest of 4.x; now the Experimental version * * Revision 4.0 89/07/24 17:02:45 nfh * Freezing rev 3. Rev 4 is now Experimental * * Revision 3.3 89/07/21 09:28:14 mlh * Discrete equitions evaluated at time given by independent variable * in the sense that the state on the left hand side refers to state(t) * and explicit dependence on t works naturally. * * Revision 1.3 89/07/21 09:14:08 mlh * Discrete equations evaluated at time given by ndependent variable * in the sense that state on the left hand side refers to state(t) * and explicit dependence on t works naturally. This is done by * incrementing t before calling discrete block and updating the * history at the beginning instead of the end. * * Revision 1.2 89/07/12 13:57:21 mlh * state@1 now refers to fianl value at previous step * state@0 is a syntax error * * Revision 1.1 89/07/06 14:48:27 mlh * Initial revision * */ #include #include "modl.h" #include "parse1.h" #include "symbol.h" void disc_var_seen(q1, q2, q3, array) /*NAME '@' NUMBER --- array flag*/ Item *q1, *q2, *q3; int array; { Symbol *s; int num; num = atoi(STR(q3)); s = SYM(q1); if (num < 1) { diag("Discrete variable must have @index >= 1", (char *)0); } num--; if (!(s->subtype & STAT)) { diag(s->name, " must be a STATE for use as discrete variable"); } if (array && !(s->subtype & ARRAY)) { diag(s->name, " must be a scalar discrete variable"); } if (!array && (s->subtype & ARRAY)) { diag(s->name, " must be an array discrete variable"); } if (s->discdim <= num) { s->discdim = num+1; } Sprintf(buf, "__%s", s->name); replacstr(q1, buf); delete(q2); Sprintf(buf, "[%d]", num); replacstr(q3, buf); } void massagediscblk(q1, q2, q3, q4) /*DISCRETE NAME stmtlist '}'*/ Item *q1, *q2, *q3, *q4; { int i; Symbol *s; Item *qs; replacstr(q1, "int"); Insertstr(q3, "()\n{\n"); Insertstr(q4, "}\n"); SYM(q2)->subtype |= DISCF; SYMITER(NAME) if (s->subtype & STAT && s->used && s->discdim) { if (s->subtype & ARRAY) { Sprintf(buf, "{int _i, _j; for (_j=%d; _j >=0; _j--) {\n\ for (_i=%d; _i>0; _i--) __%s[_i][_j] = __%s[_i-1][_j];\n\ __%s[0][_j] = %s[_j];\n\ }}\n", s->araydim -1, s->discdim -1, s->name, s->name, s->name, s->name); }else{ Sprintf(buf, "{int _i; for (_i=%d; _i>0; _i--) __%s[_i] = __%s[_i-1];\n\ __%s[0] = %s;\n}\n", s->discdim -1, s->name, s->name, s->name, s->name); } Insertstr(q3, buf); s->used = 0; } /*initialization and declaration done elsewhere*/ movelist(q1, q4, procfunc); } void init_disc_vars() { int i; Item *qs; Symbol *s; SYMITER(NAME) if (s->subtype & STAT && s->discdim) { if (s->subtype & ARRAY) { Sprintf(buf, "{int _i, _j; for (_j=%d; _j >=0; _j--) {\n\ for (_i=%d; _i>=0; _i--) __%s[_i][_j] = %s0;}}\n", s->araydim -1, s->discdim -1, s->name, s->name); Linsertstr(initfunc, buf); Sprintf(buf, "static double __%s[%d][%d];\n", s->name, s->discdim, s->araydim); Linsertstr(procfunc, buf); }else{ Sprintf(buf, "{int _i; for (_i=%d; _i>=0; _i--) __%s[_i] = %s0;}\n", s->discdim -1, s->name, s->name); Linsertstr(initfunc, buf); Sprintf(buf, "static double __%s[%d];\n", s->name, s->discdim); Linsertstr(procfunc, buf); } } } mod2c-8.2.2/src/mod2c_core/extdef.h000077500000000000000000000014541425457616700170120ustar00rootroot00000000000000/* /local/src/master/nrn/src/nmodl/extdef.h,v 4.2 1998/07/04 14:08:32 hines Exp */ "first_time", "error", "f_flux", "b_flux", "fabs", "sqrt", "sin", "cos", "tan", "acos", "asin", "atan", "atan2", "sinh", "cosh", "tanh", "floor", "ceil", "fmod", "log10", "log", "pow", "printf", "prterr", "exp", "threshold", "force", "deflate", "expfit", "derivs", "spline", "hyperbol", "revhyperbol", "sigmoid", "revsigmoid", "harmonic", "squarewave", "sawtooth", "revsawtooth", "ramp", "pulse", "perpulse", "step", "perstep", "erf", "exprand", "factorial", "gauss", "normrand", "poisrand", "poisson", "setseed", "scop_random", "boundary", "romberg", "legendre", "invert", "stepforce", "schedule", "set_seed", "nrn_pointing", "state_discontinuity", "net_send", "net_move", "net_event", "nrn_random_play", "at_time", "nrn_ghk", mod2c-8.2.2/src/mod2c_core/extdef2.h000077500000000000000000000000421425457616700170640ustar00rootroot00000000000000"romberg", "legendre", "deflate", mod2c-8.2.2/src/mod2c_core/extdef5.h000077500000000000000000000003341425457616700170730ustar00rootroot00000000000000"force", "deflate", "expfit", "derivs", "spline", "exprand", "gauss", "normrand", "poisrand", "poisson", "setseed", "scop_random", "boundary", "romberg", "invert", "stepforce", "schedule", "set_seed", "nrn_random_play", mod2c-8.2.2/src/mod2c_core/init.c000066400000000000000000000200331425457616700164600ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/init.c,v 4.5 1998/03/25 14:33:42 hines Exp */ #include "modl.h" #include "parse1.h" extern List *firstlist; extern List *units_def_for_acc; extern List *syminorder; Symbol *semi, *beginblk, *endblk; List *intoken; char buf[NRN_BUFSIZE]; /* volatile temporary buffer */ static struct { /* Keywords */ char *name; short kval; } keywords[] = { "VERBATIM", VERBATIM, "COMMENT", COMMENT, "TITLE", MODEL, "CONSTANT", CONSTANT, "PARAMETER", PARAMETER, "INDEPENDENT", INDEPENDENT, "ASSIGNED", DEPENDENT, "INITIAL", INITIAL1, "TERMINAL", TERMINAL, "DERIVATIVE", DERIVATIVE, "EQUATION", EQUATION, "BREAKPOINT", BREAKPOINT, "CONDUCTANCE", CONDUCTANCE, "SOLVE", SOLVE, "STATE", STATE, "STEPPED", STEPPED, "LINEAR", LINEAR, "NONLINEAR", NONLINEAR, "DISCRETE", DISCRETE, "FUNCTION", FUNCTION1, "FUNCTION_TABLE", FUNCTION_TABLE, "PROCEDURE", PROCEDURE, "PARTIAL", PARTIAL, "DEL2", DEL2, "DEL", DEL, "LOCAL", LOCAL, "METHOD", USING, "STEADYSTATE", USING, "SENS", SENS, "STEP", STEP, "WITH", WITH, "FROM", FROM, "FORALL", FORALL1, "TO", TO, "BY", BY, "if", IF, "else", ELSE, "while", WHILE, "START", START1, "DEFINE", DEFINE1, "KINETIC", KINETIC, "CONSERVE", CONSERVE, "PLOT", PLOT, "VS", VS, "LAG", LAG, "RESET", RESET, "MATCH", MATCH, "MODEL_LEVEL", MODEL_LEVEL, /* inserted by merge */ "SWEEP", SWEEP, "FIRST", FIRST, "LAST", LAST, "COMPARTMENT", COMPARTMENT, "LONGITUDINAL_DIFFUSION", LONGDIFUS, "PUTQ", PUTQ, "GETQ", GETQ, "IFERROR", IFERROR, "SOLVEFOR", SOLVEFOR, "UNITS", UNITS, "UNITSON", UNITSON, "UNITSOFF", UNITSOFF, "TABLE", TABLE, "DEPEND", DEPEND, "NEURON", NEURON, "SUFFIX", SUFFIX, "POINT_PROCESS", SUFFIX, "ARTIFICIAL_CELL", SUFFIX, "NONSPECIFIC_CURRENT", NONSPECIFIC, "ELECTRODE_CURRENT", ELECTRODE_CURRENT, "SECTION", SECTION, "RANGE", RANGE, "USEION", USEION, "READ", READ, "WRITE", WRITE, "VALENCE", VALENCE, "CHARGE", VALENCE, "GLOBAL", GLOBAL, "POINTER", POINTER, "BBCOREPOINTER", BBCOREPOINTER, "EXTERNAL", EXTERNAL, "INCLUDE", INCLUDE1, "CONSTRUCTOR", CONSTRUCTOR, "DESTRUCTOR", DESTRUCTOR, "NET_RECEIVE", NETRECEIVE, "BEFORE", BEFORE, /* before NEURON sets up cy' = f(y,t) */ "AFTER", AFTER, /* after NEURON solves cy' = f(y, t) */ "WATCH", WATCH, "FOR_NETCONS", FOR_NETCONS, "THREADSAFE", THREADSAFE, "PROTECT", PROTECT, "MUTEXLOCK", NRNMUTEXLOCK, "MUTEXUNLOCK", NRNMUTEXUNLOCK, 0, 0 }; /* * the following special output tokens are used to make the .c file barely * readable */ static struct { /* special output tokens */ char *name; short subtype; Symbol **p; } special[] = { ";", SEMI, &semi, "{", BEGINBLK, &beginblk, "}", ENDBLK, &endblk, 0, 0, 0 }; static struct { /* numerical methods */ char *name; long subtype; /* All the types that will work with this */ short varstep; } methods[] = { "adams", DERF | KINF, 0, "runge", DERF | KINF, 0, "euler", DERF | KINF, 0, "adeuler", DERF | KINF, 1, "heun", DERF | KINF, 0, "adrunge", DERF | KINF, 1, "gear", DERF | KINF, 1, "newton", NLINF, 0, "simplex", NLINF, 0, "simeq", LINF, 0, "seidel", LINF, 0, "_advance", KINF, 0, "sparse", KINF, 0, "derivimplicit", DERF, 0, /* name hard wired in deriv.c */ "cnexp", DERF, 0, /* see solve.c */ "clsoda", DERF | KINF, 1, /* Tolerance built in to scopgear.c */ "after_cvode", 0, 0, "cvode_t", 0, 0, "cvode_t_v", 0, 0, 0, 0, 0 }; static char *extdef[] = { /* external names that can be used as doubles * without giving an error message */ #include "extdef.h" 0 }; static char *extdef2[] = { /* external function names that can be used * with array and function name arguments */ #include "extdef2.h" 0 }; static char *extdef3[] = { /* function names that get two reset arguments * added */ "threshold", "squarewave", "sawtooth", "revsawtooth", "ramp", "pulse", "perpulse", "step", "perstep", "stepforce", "schedule", 0 }; static char *extdef4[] = { /* functions that need a first arg of NrnThread* */ "at_time", 0 }; static char *extdef5[] = { /* the extdef names that are not threadsafe */ #include "extdef5.h" 0 }; List *constructorfunc, *destructorfunc; void init() { int i; Symbol *s; symbol_init(); for (i = 0; keywords[i].name; i++) { s = install(keywords[i].name, keywords[i].kval); s->subtype = KEYWORD; } for (i = 0; methods[i].name; i++) { s = install(methods[i].name, METHOD); s->subtype = methods[i].subtype; s->u.i = methods[i].varstep; } for (i = 0; special[i].name; i++) { s = install(special[i].name, SPECIAL); *(special[i].p) = s; s->subtype = special[i].subtype; } for (i = 0; extdef[i]; i++) { s = install(extdef[i], NAME); s->subtype = EXTDEF; } for (i = 0; extdef2[i]; i++) { s = install(extdef2[i], NAME); s->subtype = EXTDEF2; } for (i = 0; extdef3[i]; i++) { s = lookup(extdef3[i]); assert(s && (s->subtype & EXTDEF)); s->subtype |= EXTDEF3; } for (i = 0; extdef4[i]; i++) { s = lookup(extdef4[i]); assert(s && (s->subtype & EXTDEF)); s->subtype |= EXTDEF4; } for (i = 0; extdef5[i]; i++) { s = lookup(extdef5[i]); assert(s); s->subtype |= EXTDEF5; } intoken = newlist(); initfunc = newlist(); modelfunc = newlist(); termfunc = newlist(); procfunc = newlist(); initlist = newlist(); firstlist = newlist(); syminorder = newlist(); plotlist = newlist(); constructorfunc = newlist(); destructorfunc = newlist(); units_def_for_acc = newlist(); acc_present_list = newlist(); #if NMODL nrninit(); #endif } mod2c-8.2.2/src/mod2c_core/io.c000066400000000000000000000252171425457616700161350ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* file.mod input routines */ #include #include #include #include #include #include "modl.h" #include #if MAC && TARGET_API_MAC_CARBON #include #endif #undef METHOD #include "parse1.h" #include "portability.h" static int isend(); static void pop_file_stack(); static int file_stack_empty(); int in_comment_; char *inputline() { /* and removes comment, newline, beginning and trailing blanks */ /* used to get the TITLE line */ char *cp; int i; buf[0] = '\0'; cp = Gets(buf); i = strlen(buf); if (i) buf[i - 1] = '\0'; if ((cp = index(buf, '!')) != (char *) 0) { *cp-- = '\0'; } while (cp >= buf && isspace(*cp)) { *cp-- = '\0'; } /*EMPTY*/ for (cp = buf; *cp != '\0' && isspace(*cp); cp++){ ; } return stralloc(cp, (char *) 0); } static int linenum = 0; void inblock(s) char *s; { /* copy input verbatim to intoken up to END*s * error if we get the whole input */ char *cp; int l; Item *q; l = linenum; for (;;) { cp = Gets(buf); if (cp == (char *) 0) { linenum = l; diag(s, " block goes to end of file"); } if (isend(s, buf)) { break; } q = putintoken(buf, STRING); q->itemtype = VERBATIM; } } static int isend(s, buf) char *s, *buf; { /* if first chars in buf form a keyword return 1 */ char *cp, word[100], *wp, test[30]; int yesno = 0; cp = buf; Sprintf(test, "END%s", s); while (*cp == ' ' || *cp == '\t') cp++; if (isalpha(*cp)) { for (wp = word; isalpha(*cp);) { *wp++ = *cp++; } *wp = '\0'; if (strcmp(test, word) == 0) { yesno = 1; } } return yesno; } /* * We painfully constuct our own input buffer so that when user errors occur * we can print the whole line. Often, even this is not enough if the error * is at the end of a line. We also count lines so the user can go right to * the error in most cases */ static char inlinebuf[2][NRN_BUFSIZE], *inlinep = inlinebuf[0] + 30, *ctp = inlinebuf[0] + 30; static int whichbuf; char* Fgets(buf, size, f) char* buf; int size; FILE* f; { char* p = buf; int c, i; for(i=0; i < size; ++ i) { c = getc(f); if (c == EOF || c == 26 || c == 4) { /* ^Z and ^D are end of file */ /* some editors don't put a newline at last line */ if ( p > buf) { ungetc(c, f); c = '\n'; }else{ break; } } if (c == '\r') { int c2 = getc(f); if (c2 != '\n') { ungetc(c2, f); } c = '\n'; } if (c < 0 || c > 127) { *p++ = '\n'; *p='\0'; if (!in_comment_) { diag("Non-Ascii character in file:", buf); } return buf; } *p++ = c; if (c == '\n') { *p = '\0'; return buf; } } if (i >= size) { buf[size-1] = 0; diag("Line too long:", buf); } return (char*)0; } int Getc() { int c; if (ctp == (char *) 0 || *ctp == '\0') { whichbuf = (whichbuf?0:1); inlinep = inlinebuf[whichbuf] + 30; ctp = Fgets(inlinep, 512, fin); if (ctp) linenum++; } if (ctp == (char *) 0) { ctp = inlinep; *ctp = '\0'; if (file_stack_empty()) { return EOF; }else{ pop_file_stack(); return Getc(); } } c = *ctp++; return c; } int unGetc(c) int c; { if (c == EOF) return c; if (ctp > inlinebuf[whichbuf]) { ctp--; *ctp = c; } else { diag("internal error in unGetc", ""); } return c; } char *Gets(buf) char *buf; { char *cp; int c; cp = buf; while ((c = Getc()) != EOF && c != '\n') { *cp++ = c; } if (c == '\n') { *cp++ = c; *cp++ = '\0'; return buf; } else if (c == EOF) { return (char *) 0; } else { diag("internal error in Gets()", ""); } return (char *) 0; } #if 0 /* not currently used */ void unGets(buf) /* all this because we don't have an ENDBLOCK * keyword */ char *buf; { if (ctp != '\0') { /* can only be called after successful Gets */ Strcpy(inlinep, buf); ctp = inlinep; } else { diag("internal error in unGets()", ""); } } #endif char* current_line() { /* assumes we actually want the previous line */ static char buf[NRN_BUFSIZE]; char* p; sprintf(buf,"at line %d in file %s:\\n%s", linenum-1, finname, inlinebuf[whichbuf?0:1]+30); for (p = buf; *p; ++p) { if (*p == '\n') { *p = '\0'; } if (*p == '"') { *p = '\047'; } } return buf; } /* two arguments so we can pass a name to construct an error message. */ void diag(s1, s2) char *s1, *s2; { char *cp; Fprintf(stderr, "%s", s1); if (s2) { Fprintf(stderr, "%s", s2); } if (fin) { Fprintf(stderr, " at line %d in file %s\n", linenum, finname); Fprintf(stderr, "%s", inlinep); if (ctp >= inlinep) { for (cp = inlinep; cp < ctp - 1; cp++) { if (*cp == '\t') { Fprintf(stderr, "\t"); } else { Fprintf(stderr, " "); } } Fprintf(stderr, "^"); } } Fprintf(stderr, "\n"); #if MAC && TARGET_API_MAC_CARBON SIOUXSettings.autocloseonquit = true; RunApplicationEventLoop(); #endif exit(1); } #if 0 static Symbol *symq[20], **symhead = symq, **symtail = symq; /* * the following is a nonsensical implementation of heirarchical model * building. Disregard. It assumes .mod files can be concatenated to produce * meaningful models. It was this insanity which prompted us to allow use of * variables before declaration */ void enquextern(sym) Symbol *sym; { *symtail++ = sym; } FILE *dequextern() { char fname[20]; FILE *f; Symbol *s; if (symhead >= symtail) return (FILE *) 0; s = *symhead++; Sprintf(fname, "%s.mod", s->name); f = fopen(fname, "r"); if (f == (FILE *) 0) { diag("Can't open", fname); } Fclose(fin); linenum = 0; Strcpy(finname, fname); return f; } #endif typedef struct FileStackItem { char* inlinep; char* ctp; int linenum; FILE* fp; char finname[NRN_BUFSIZE]; } FileStackItem; static List* filestack; static int getprefix(prefix, s) char* prefix, *s; { char* cp; strcpy(prefix, s); for (cp = prefix + strlen(prefix); cp+1 != prefix; --cp) { if (*cp == '/') { break; } *cp = '\0'; } return (prefix[0] != '\0'); } static FILE* include_open(fname, err) char* fname; int err; { FILE* f = (FILE*)0; FileStackItem* fsi; char* dirs, *colon; char buf2[NRN_BUFSIZE]; if(fname[0] == '/') { /* highest precedence is complete filename */ return fopen(fname, "r"); } fsi = (FileStackItem*)(SYM(filestack->prev)); if (getprefix(buf, fsi->finname)) { strcat(buf, fname); f = fopen(buf, "r"); /* first try in directory of last file */ if (f) { strcpy(fname, buf); return f; } if (err) fprintf(stderr, "Couldn't open: %s\n", buf); } f = fopen(fname, "r"); /* next try current working directory */ if (f) { return f; } sprintf(buf, "../%s", fname); /* Next try next dir up. */ if ((f = fopen(buf, "r")) != NULL) return f; if (err) fprintf(stderr, "Couldn't open: %s\n", fname); /* try all the directories in the environment variable */ /* a colon separated list of directories */ dirs = getenv("MODL_INCLUDE"); if (dirs) { strcpy(buf, dirs); dirs = buf; colon = dirs; for (dirs = colon; *dirs; dirs = colon){ for(; *colon; ++colon) { if (*colon == ':') { *colon = '\0'; ++colon; break; } } strcpy(buf2, dirs); strcat(buf2, "/"); strcat(buf2, fname); f = fopen(buf2, "r"); if (f) { strcpy(fname, buf2); return f; } if (err) fprintf(stderr, "Couldn't open: %s\n", buf2); } } return f; } void include_file(q) Item* q; { char fname[NRN_BUFSIZE]; FileStackItem* fsi; if (!filestack) { filestack = newlist(); } strcpy(fname, STR(q) + 1); fname[strlen(fname)-1] = '\0'; fsi = (FileStackItem*)emalloc(sizeof(FileStackItem)); lappendsym(filestack, (Symbol*)fsi); fsi->inlinep = inlinep; fsi->ctp = ctp; fsi->linenum = linenum; fsi->fp = fin; strcpy(fsi->finname, finname); if ((fin = include_open(fname, 0)) == (FILE*)0) { include_open(fname, 1); diag("Couldn't open ", fname); } fprintf(stderr, "INCLUDEing %s\n", fname); strcpy(finname, fname); ctp = (char*)0; linenum = 0; } static void pop_file_stack() { FileStackItem* fsi; fsi = (FileStackItem*)(SYM(filestack->prev)); delete(filestack->prev); linenum = fsi->linenum; inlinep = fsi->inlinep; fclose(fin); fin = fsi->fp; strcpy(finname, fsi->finname); free((char*)fsi); } static int file_stack_empty() { if (!filestack) { return 1; } return (filestack->next == filestack); } /* adapted from : gist@jonathonreinhart/mkdir_p.c */ int mkdir_p(const char *path) { const size_t len = strlen(path); char mypath[PATH_MAX]; char *p; errno = 0; /* copy string so its mutable */ if (len > sizeof(mypath)-1) { fprintf(stderr, "Output directory path too long\n"); return -1; } strcpy(mypath, path); /* iterate the string */ for (p = mypath + 1; *p; p++) { if (*p == '/') { /* temporarily truncate */ *p = '\0'; if (mkdir(mypath, S_IRWXU) != 0) { if (errno != EEXIST) return -1; } *p = '/'; } } if (mkdir(mypath, S_IRWXU) != 0) { if (errno != EEXIST) return -1; } return 0; } mod2c-8.2.2/src/mod2c_core/kinetic.c000066400000000000000000001311011425457616700171420ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" #define Glass 1 #if Glass /* We have found and corrected an MODL bug. The problem is that if any directive other than a CONSERVE or ~ is used within a KINETIC block the resultant C code is not in the correct order. Here is the C code from a kinetic block: */ #endif /* Sets up derivative form and implicit form*/ #include #include "modl.h" #include "parse1.h" #include "symbol.h" extern int numlist; extern int thread_data_index; extern List* thread_cleanup_list; #if VECTORIZE extern int vectorize; #endif extern Symbol *indepsym; #if CVODE int singlechan_; static int cvode_flag; static void cvode_kin_remove(); static Item* cvode_sbegin, *cvode_send; static List* kin_items_; #define CVODE_FLAG if(cvode_flag) #define NOT_CVODE_FLAG if(!cvode_flag) #else #define CVODE_FLAG if(0) #define NOT_CVODE_FLAG if(1) #endif typedef struct Rterm { struct Rterm *rnext; Symbol *sym; char *str; int num; short isstate; /* 1 if to be solved for */ } Rterm; static Rterm *rterm = (Rterm *)0, *lterm; /*list of reaction terms for a side*/ typedef struct Reaction { struct Reaction *reactnext; Rterm *rterm[2]; /* rterm[0] = null if flux*/ char *krate[2]; /* one of these is null if flux */ Item *position; } Reaction; static Reaction *reactlist = (Reaction *)0; static Reaction *conslist = (Reaction *)0; static List *done_list; /* list of already translated blocks */ static List *done_list1; /* do not emit definitions more than once */ typedef struct Rlist { Reaction *reaction; Symbol *sym; /* the kinetic block symbol */ Item *position; /* where we can initialize lists */ Item *endbrace; /* can insert after all statements */ Symbol **symorder; /* state symbols in varnum order */ char **capacity; /* compartment size expessions in varnum order */ int nsym; /* number of symbols in above vector */ int ncons; /* and the diagonals for conservation are first */ int sens_parm; /* for possible error message later on */ struct Rlist *rlistnext; int slist_decl; } Rlist; static Rlist *rlist = (Rlist *)0; static Rlist *clist = (Rlist *)0; static List *compartlist; /* list of triples with point to info in COMPARTMENT statement. The info is qexpr q'{' q'}' and points to items safely enclosed in a C comment. see massagecompart() and massagekinetic() */ List *ldifuslist; /* analogous to compartment. Specifies diffusion constant times the relevant cross sectional area. The volume/length must be specified in the COMPARTMENT statement */ /* addition of sens statement handling is restricted to the derivative form and follows the way it is done in deriv.c with the following exception-- until the solve statement is dealt with in solve.c we dont know which form we will use for the equations. Therefore we save sensused in the main Rlist and give error message if it is non-zero when implicit is called. Also the sensmassage call in massagekinetic substitutes an intermediate block to be called by the integrator and gives the total number of states including the sens states. This means that the call to kinetic_intmethod gets the new fun with too many states and therefore should rely only on the lists in this routine for its info. */ extern int sens_parm; static int genconservterms(); static int number_states(); static void kinlist(); static void genderivterms(); static void genmatterms(); #define MAXKINBLK 20 static int nstate_[MAXKINBLK]; #if VECTORIZE static char* instance_loop() { extern char* cray_pragma(); static char buf1[NRN_BUFSIZE]; Sprintf(buf1, "\n#ifdef WANT_PRAGMA%s#endif\n _INSTANCE_LOOP {\n", cray_pragma()); return buf1; } #endif static int sparse_declared_[10]; static int sparsedeclared(i) int i; { assert(i < 10); return sparse_declared_[i]++; } char *qconcat(q1, q2) /* return names as single string */ Item *q1, *q2; { char *cp, *ovrfl, *cs, *n; cp = buf; ovrfl = buf+400; while (q1 != q2->next) { assert(cp < ovrfl); *cp++ = ' '; if (q1->itemtype == SYMBOL) { /* dont prepend *( to ARRAYS anymore */ #if 0 if (SYM(q1)->type == NAME && (SYM(q1)->subtype & ARRAY)) { *cp++ = '*'; *cp++ = '('; } #endif n = SYM(q1)->name; } else { n = STR(q1); } for (cs = n; *cs; cs++) { *cp++ = *cs; } q1 = q1->next; } *cp = '\0'; return stralloc(buf, (char *)0); } void reactname(q1, lastok, q2) /* NAME [] INTEGER q2 may be null*/ Item *q1, *lastok, *q2; { /* put on right hand side */ Symbol *s, *s1; Rterm *rnext; rnext = rterm; rterm = (Rterm *)emalloc(sizeof(Rterm)); rterm->rnext = rnext; rterm->isstate = 0; s = SYM(q1); if ((s->subtype & STAT) && in_solvefor(s)) { Sprintf(buf, "D%s", s->name); s1 = lookup(buf); s1->usage |= DEP; s->used++; rterm->isstate = 1; } else if (!(s->subtype & (DEP | nmodlCONST | PARM | INDEP | STEP1 | STAT)) ) { diag(s->name, " must be a STATE, CONSTANT, ASSIGNED, STEPPED, or INDEPENDENT"); } if (q2) { rterm->num = atoi(STR(q2)); }else{ rterm->num = 1; } if (q1 != lastok) { if(!(s->subtype & ARRAY)) { diag("REACTION: MUST be scalar or array", (char *)0); } rterm->str = qconcat(q1->next->next, lastok->prev); /* one too many parentheses since normally a *( is prepended to the name during output in cout.c. Therefore when used to construct a MATELM or RHS extra parentheses must be prepended as in MATELM((...,(.... */ /* this no longer holds, no parentheses are to be prepended */ } else { rterm->str = (char *)0; } rterm->sym = s; } void leftreact() /* current reaction list is for left hand side */ { /* put whole list on left hand side and initialize right hand side */ lterm = rterm; rterm = (Rterm *)0; } void massagereaction(qREACTION, qREACT1, qlpar, qcomma, qrpar) Item *qREACTION, *qREACT1, *qlpar, *qcomma, *qrpar; { Reaction *r1; /*ARGSUSED*/ r1 = reactlist; reactlist = (Reaction *)emalloc(sizeof(Reaction)); reactlist->reactnext = r1; reactlist->rterm[1] = rterm; reactlist->rterm[0] = lterm; reactlist->krate[0] = qconcat(qlpar->next, qcomma->prev); reactlist->krate[1] = qconcat(qcomma->next, qrpar->prev); reactlist->position = qrpar; /*SUPPRESS 440*/ replacstr(qREACTION, "/* ~"); /*SUPPRESS 440*/ Insertstr(qrpar, ")*/\n"); /*SUPPRESS 440*/ replacstr(qrpar, "/*REACTION*/\n"); rterm = (Rterm *)0; } void flux(qREACTION, qdir, qlast) Item *qREACTION, *qdir, *qlast; { Reaction *r1; r1 = reactlist; reactlist = (Reaction *)emalloc(sizeof(Reaction)); reactlist->reactnext = r1; reactlist->rterm[0] = rterm; reactlist->rterm[1] = (Rterm *)0; /*SUPPRESS 440*/ replacstr(qREACTION, "/* ~"); reactlist->position = qlast; if (SYM(qdir)->name[0] == '-') { reactlist->krate[0] = qconcat(qdir->next->next, qlast); reactlist->krate[1] = (char *)0; /*SUPPRESS 440*/ replacstr(qlast, "/*REACTION*/\n"); }else{ if (rterm->rnext || (rterm->num != 1)) { diag("flux equations involve only one state", (char *)0); } reactlist->krate[0] = (char *)0; reactlist->krate[1] = qconcat(qdir->next->next, qlast); #if NOCMODL if (ldifuslist) { /* function of current ? */ Item* q; int isfunc; for (q = qdir->next->next; q != qlast; q = q->next) { Symbol* s; if (q->itemtype == SYMBOL) { s = SYM(q); if (s->nrntype & 02 /*NRNCURIN*/) { Symbol* sr; Item* q1; char* c1, *c2; /* associate dflux/dcur with proper state */ ITERATE(q1, ldifuslist) { sr = SYM(q1); q1 = q1->next->next->next->next->next; if (sr == rterm->sym) { c1 = qconcat(qdir->next->next, q->prev); c2 = qconcat(q->next, qlast); sprintf(buf, "nrn_nernst_coef(_type_%s)*(%s _ion_d%sdv %s)", s->name, c1, s->name, c2); /* dflux/dv */ if (rterm->str) { replacstr(q1, rterm->str); } if (*STR(q1->next) == '\0') { replacstr(q1->next, buf); }else{ diag(sr->name, "gets a flux from more than one current"); } } q1 = q1->next; } } } } } #endif /*SUPPRESS 440*/ replacstr(qlast, "/*FLUX*/\n"); } /*SUPPRESS 440*/ Insertstr(qlast, ")*/\n"); /*SUPPRESS 440*/ rterm = (Rterm *)0; } /* set up derivative form for use with integration methods */ /* a bunch of states may be marked used but not be in the solveforlist we therefore loop through all the rterms and mark only those */ void massagekinetic(q1, q2, q3, q4, sensused) /*KINETIC NAME stmtlist '}'*/ Item *q1, *q2, *q3,*q4; int sensused; { int count = 0, i, order, ncons; Item *q, *qs, *afterbrace; Item* qv; Symbol *s, *fun; Reaction *r1; Rterm *rt; Rlist *r; fun = SYM(q2); if ((fun->subtype & (DERF|KINF)) && fun->u.i) { diag("Merging kinetic blocks not implemented", (char *)0); } fun->subtype |= KINF; numlist++; fun->u.i = numlist; #if 0 Sprintf(buf, "static int %s();\n", SYM(q2)->name); Linsertstr(procfunc, buf); replacstr(q1, "\nstatic int"); #else Sprintf(buf, "\n" "/* _kinetic_ %s %s */\n" "#ifndef INSIDE_NMODL\n" "#define INSIDE_NMODL\n" "#endif\n" , SYM(q2)->name, suffix); Linsertstr(procfunc, buf); Sprintf(buf, "\nstruct %s%s {\n int operator()(SparseObj* _so, double* _rhs, _threadargsproto_) const;\n};\nint", SYM(q2)->name, suffix); replacstr(q1, buf); Sprintf(buf, "%s%s::operator()", SYM(q2)->name, suffix); replacstr(q2, buf); #endif qv = insertstr(q3, "()\n"); #if VECTORIZE if (vectorize) { kin_vect1(q1, q2, q4); vectorize_substitute(qv, "(SparseObj* _so, double* _rhs, _threadargsproto_) const\n"); } #endif qv = insertstr(q3, "{_reset=0;\n"); #if VECTORIZE Sprintf(buf, "{int _reset=0;\n"); vectorize_substitute(qv, buf); #endif afterbrace = q3->next; #if Glass /* Make sure that if the next statement was LOCAL xxx, we skip past it to do any of the other declarations. DRB */ if(afterbrace->itemtype==STRING && !strcmp(afterbrace->element.str,"double")){ for(afterbrace = afterbrace->next ; afterbrace->itemtype!=STRING || strcmp(afterbrace->element.str,";\n") ; afterbrace=afterbrace->next); if(afterbrace->itemtype==STRING && !strcmp(afterbrace->element.str,";\n")) afterbrace=afterbrace->next; } #endif qv = insertstr(afterbrace, "double b_flux, f_flux, _term; int _i;\n"); #if 0 && VECTORIZE vectorize_substitute(qv, "int _i;\n"); #endif /* also after these declarations will go initilization statements */ order = 0; /* the varnum and order of the states is such that diagonals of conservation equations must be first. This is done by setting s->used=-1 for all states and then numbering first with respect to the conslist and then the remaining that are still -1 */ /* mark only the isstate states */ SYMITER(NAME) { if ((s->subtype & STAT) && s->used) { s->used = 0; } } for (r1 = conslist; r1; r1 = r1->reactnext) { for (rt = r1->rterm[0]; rt; rt = rt->rnext) { if (rt->isstate) { rt->sym->used = -1; } } } for (r1 = reactlist; r1; r1 = r1->reactnext) { for (rt = r1->rterm[0]; rt; rt = rt->rnext) { if (rt->isstate) { rt->sym->used = -1; } } for (rt = r1->rterm[1]; rt; rt = rt->rnext) { if (rt->isstate) { rt->sym->used = -1; } } } /* diagonals of the conservation relations are first */ for (r1 = conslist; r1; r1 = r1->reactnext) { for (rt = r1->rterm[0]; rt; rt = rt->rnext) { if ((rt->sym->used == -1) && !(rt->sym->subtype & ARRAY)) { rt->sym->varnum = count++; rt->sym->used = ++order; /*first is 1*/ break; } } if (!rt) { diag("Failed to diagonalize the Kinetic matrix", (char *)0); } } ncons = count; /* can't use array as conservation diagonal */ /* others can be in any order */ SYMITER(NAME) { if ((s->subtype & STAT) && s->used == -1) { s->varnum = count; s->used = ++order; /* count and order distinct states */ if (s->subtype & ARRAY) { int dim = s->araydim; count += dim; }else{ count++; } } } if (count == 0) { diag("KINETIC contains no reactions", (char *)0); } fun->used = count; Sprintf(buf, ", _slist%d[0:%d], _dlist%d[0:%d]", numlist, count, numlist, count); Lappendstr(acc_present_list, buf); Sprintf(buf, "\n#define _slist%d _slist%d%s\n" "int* _slist%d;\n" "#pragma acc declare create(_slist%d)\n" "\n#define _dlist%d _dlist%d%s\n" "int* _dlist%d;\n" "#pragma acc declare create(_dlist%d)\n" , numlist, numlist, suffix, numlist, numlist , numlist, numlist, suffix, numlist, numlist ); Linsertstr(procfunc, buf); insertstr(q4, " } return _reset;\n"); movelist(q1, q4, procfunc); r = (Rlist *)emalloc(sizeof(Rlist)); r->reaction = reactlist; reactlist = (Reaction *)0; r->sens_parm = sens_parm; r->symorder = (Symbol **)emalloc((unsigned)order*sizeof(Symbol *)); r->slist_decl = 0; /*the reason that we can't just keep this info in s->varnum is that more than one block can have the same state with a different varnum */ SYMITER(NAME) { if ((s->subtype & STAT) && s->used) { r->symorder[s->used - 1] = s; if (sensused) { add_sens_statelist(s); } } } r->nsym = order; r->ncons = ncons; r->position = afterbrace; r->endbrace = q4->prev; /* needed for Dstate with COMPARTMENT */ if (sensused) { /* fun now is the interface and fun->used is all the states */ sensmassage(DERIVATIVE, q2, numlist); /* this sets sens_parm to 0 */ } r->sym = fun; r->rlistnext = rlist; rlist = r; r = (Rlist *)emalloc(sizeof(Rlist)); r->reaction = conslist; conslist = (Reaction *)0; r->sym = fun; r->rlistnext = clist; clist = r; /* handle compartlist if any */ rlist->capacity = (char **)emalloc((unsigned)order*sizeof(char *)); for (i=0; icapacity[i] = ""; } if (compartlist) { char buf1[NRN_BUFSIZE]; Item *q, *qexp, *qb, *qend, *q1; ITERATE(q, compartlist) { qexp = ITM(q); q = q->next; qb = ITM(q); q = q->next; qend = ITM(q); for (q1 = qb->next; q1 != qend; q1 = q1->next) { Sprintf(buf1, "(%s)", qconcat(qexp, qb->prev)); rlist->capacity[SYM(q1)->used - 1] = stralloc(buf1, (char *)0); } } freelist(&compartlist); } SYMITER(NAME) { if ((s->subtype & STAT) && s->used) { s->used = 0; } } #if CVODE cvode_sbegin = q3; cvode_send = q4; kin_items_ = newlist(); for (q = cvode_sbegin; q != cvode_send->next; q = q->next) { lappenditem(kin_items_, q); } #endif } #if Glass void fixrlst(rlst) Rlist *rlst; { if(rlst->position->prev->itemtype==STRING && !strcmp(rlst->position->prev->element.str,"error =")) { rlst->position=rlst->position->prev; } } #endif static int ncons; /* the number of conservation equations */ void kinetic_intmethod(fun, meth) Symbol *fun; char* meth; { /*derivative form*/ Reaction *r1; Rlist *rlst, *clst; int i, nstate; cvode_kin_remove(); nstate = number_states(fun, &rlst, &clst); if (ncons) { Fprintf(stderr, "%s method ignores conservation\n", meth); } ncons = 0; Sprintf(buf, "{int _i; for(_i=0;_i<%d;_i++) _p[_dlist%d[_i]] = 0.0;}\n", nstate, fun->u.i); /*goes near beginning of block*/ #if Glass fixrlst(rlst); #endif Insertstr(rlst->position, buf); for (r1=rlst->reaction; r1; r1 = r1->reactnext) { genderivterms(r1, 0, 0); } for (i = 0; i < rlst->nsym; i++) { if (rlst->capacity[i][0]) { if (rlst->symorder[i]->subtype & ARRAY) { Sprintf(buf, "for (_i=0; _i < %d; _i++) { _p[_dlist%d[_i + %d]] /= %s;}\n", rlst->symorder[i]->araydim, fun->u.i, rlst->symorder[i]->varnum, rlst->capacity[i]); Insertstr(rlst->endbrace, buf); }else{ Sprintf(buf, "_p[_dlist%d[%d]] /= %s;\n", fun->u.i, rlst->symorder[i]->varnum, rlst->capacity[i]); Insertstr(rlst->endbrace, buf); } } } kinlist(fun, rlst); } static void genderivterms(r, type, n) Reaction *r; int type; /* 0 derivative, 1 implicit */ int n; /* function number, needed only for implicit */ { Symbol *s; Item *q; Rterm *rt; int i, j; if (r->rterm[1] == (Rterm *)0 && r->krate[1]) { genfluxterm(r, type, n); return; } q = r->position; for (j=0; j<2; j++) { if (j == 0) { Insertstr(q, "f_flux ="); }else{ Insertstr(q, ";\n b_flux ="); } if (r->krate[j]) { Insertstr(q, r->krate[j]); }else{ Insertstr(q, "0."); } for (rt = r->rterm[j]; rt; rt = rt->rnext) { for (i=0; inum; i++) { Insertstr(q, "*"); Insertsym(q, rt->sym); if (rt->str) { Sprintf(buf, "[%s]", rt->str); Insertstr(q, buf); } } } } Insertstr(q, ";\n"); for (j=0; j<2; j++) { for (rt = r->rterm[j]; rt; rt = rt->rnext) { if (!(rt->isstate)) { continue; } Sprintf(buf, "D%s", rt->sym->name); s = lookup(buf); s->usage |= DEP; if (rt->sym->varnum < ncons) continue; /* equation reserved for conservation*/ if (type) { Sprintf(buf, "_RHS%d(", n); Insertstr(q, buf); if (rt->str) { Sprintf(buf, "%d + %s)", rt->sym->varnum, rt->str); } else { Sprintf(buf, "%d)", rt->sym->varnum); } Insertstr(q, buf); }else{ Insertsym(q, s);/*needs processing in cout*/ if (rt->str) { Sprintf(buf, "[%s]", rt->str); Insertstr(q, buf); } } if (j == 0) { Insertstr(q, "-="); }else{ Insertstr(q, "+="); } if (rt->num > 1) { Sprintf(buf, "%d.0 *", rt->num); Insertstr(q, buf); } Insertstr(q, "(f_flux - b_flux);\n"); } } Insertstr(q, "\n"); /* REACTION comment left in */ } void genfluxterm(r, type, n) Reaction *r; int type; int n; { Symbol *s; Rterm *rt; Item *q; q = r->position; rt = r->rterm[0]; if (!(rt->isstate)) { diag(rt->sym->name, " must be (solved) STATE in flux reaction"); } Sprintf(buf, "D%s", rt->sym->name); s = lookup(buf); if (rt->sym->varnum < ncons) diag(rt->sym->name, " is conserved and has a flux"); /* the right hand side */ Insertstr(q, "f_flux = b_flux = 0.;\n"); if (type) { Sprintf(buf, "_RHS%d(", n); Insertstr(q, buf); if (rt->str) { Sprintf(buf, "%d + %s)", rt->sym->varnum, rt->str); } else { Sprintf(buf, "%d)", rt->sym->varnum); } Insertstr(q, buf); }else{ Insertsym(q, s);/*needs processing in cout*/ if (rt->str) { Sprintf(buf, "[%s]", rt->str); Insertstr(q, buf); } } if (r->krate[0]) { Sprintf(buf, " -= (f_flux = (%s) * ", r->krate[0]); Insertstr(q, buf); Insertsym(q, rt->sym); if (rt->str) { Sprintf(buf, "[%s]", rt->str); Insertstr(q, buf); } }else{ Insertstr(q, "+= (b_flux = "); Insertstr(q, r->krate[1]); } Insertstr(q, ");\n"); /* the matrix coefficient */ if (type && r->krate[0]) { Sprintf(buf, " _MATELM%d(", n); Insertstr(q, buf); if (rt->str) { Sprintf(buf, "%d + %s, %d + %s", rt->sym->varnum, rt->str, rt->sym->varnum, rt->str); }else{ Sprintf(buf, "%d, %d)", rt->sym->varnum, rt->sym->varnum); } Insertstr(q, buf); Sprintf(buf, "+= %s;\n", r->krate[0]); Insertstr(q, buf); } } static int linmat; /* 1 if linear */ void kinetic_implicit(fun, dt, mname) Symbol *fun; char *dt, *mname; /* mname is _advance or sparse */ { /*implicit equations _slist are state(t+dt) _dlist are Dstate(t)*/ Item *q; Item* qv; Reaction *r1; Rlist *rlst, *clst; int i, nstate, flag, sparsedec, firsttrans, firsttrans1; firsttrans = 0; /* general declarations done only for NOT_CVODE_FLAG */ firsttrans1 = 0; cvode_kin_remove(); nstate = number_states(fun, &rlst, &clst); CVODE_FLAG { ncons = 0; Sprintf(buf, "static void* _cvsparseobj%d;\n", fun->u.i); q = linsertstr(procfunc, buf); sprintf(buf, "static int _cvspth%d = %d;\n", fun->u.i, thread_data_index++); vectorize_substitute(q, buf); sprintf(buf, " _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_cvspth%d]._pvoid);\n", fun->u.i); lappendstr(thread_cleanup_list, buf); }else{ if (!done_list) { done_list = newlist(); done_list1 = newlist(); } firsttrans = 1; /* declare the sparseobj and linflag*/ firsttrans1 = 1; ITERATE(q, done_list) { if (SYM(q) == fun) { firsttrans = 0; /* already declared */ } } ITERATE(q, done_list1) { if (SYM(q) == fun) { firsttrans1 = 0; /* already declared */ } } if (firsttrans1) { Lappendsym(done_list, fun); Lappendsym(done_list1, fun); Sprintf(buf, "static void* _sparseobj%d;\n", fun->u.i); q = linsertstr(procfunc, buf); sprintf(buf, "static int _spth%d = %d;\n", fun->u.i, thread_data_index++); vectorize_substitute(q, buf); sprintf(buf, " _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_spth%d]._pvoid);\n", fun->u.i); lappendstr(thread_cleanup_list, buf); } } if (rlst->sens_parm) { diag(" SENS unimplemented for default kinetic integration", " method"); } /*goes near beginning of block. Before first reaction is not adequate since the first reaction may be within a while loop */ #if Glass fixrlst(rlst); #endif CVODE_FLAG { Insertstr(rlst->position, " b_flux = f_flux = 0.;\n"); } Sprintf(buf, "{int _i; double _dt1 = 1.0/%s;\n\ for(_i=%d;_i<%d;_i++){\n", dt, ncons, nstate); Insertstr(rlst->position, buf); qv = insertstr(rlst->position, ""); #if 0 && VECTORIZE vectorize_substitute(qv, instance_loop()); #endif NOT_CVODE_FLAG { Sprintf(buf, "\ _RHS%d(_i) = -_dt1*(_p[_slist%d[_i]*_STRIDE] - _p[_dlist%d[_i]*_STRIDE]);\n\ _MATELM%d(_i, _i) = _dt1;\n", fun->u.i, fun->u.i, fun->u.i, fun->u.i); qv = insertstr(rlst->position, buf); #if 0 && VECTORIZE Sprintf(buf, "\ _RHS%d(_i) = -_dt1*(_p[_ix][_slist%d[_i]] - _p[_ix][_dlist%d[_i]]);\n\ _MATELM%d(_i, _i) = _dt1;\n", fun->u.i, fun->u.i, fun->u.i, fun->u.i); vectorize_substitute(qv, buf); #endif } CVODE_FLAG { Sprintf(buf, "\ _RHS%d(_i) = _dt1*(_p[_dlist%d[_i]]);\n\ _MATELM%d(_i, _i) = _dt1;\n", fun->u.i, fun->u.i, fun->u.i); qv = insertstr(rlst->position, buf); #if 0 && VECTORIZE Sprintf(buf, "\ _RHS%d(_i) = _dt1*(_p[_ix][_dlist%d[_i]]);\n\ _MATELM%d(_i, _i) = _dt1;\n", fun->u.i, fun->u.i, fun->u.i); vectorize_substitute(qv, buf); #endif } qv = insertstr(rlst->position, ""); #if 0 && VECTORIZE vectorize_substitute(qv, " } /* ILOOPEND */\n"); #endif Sprintf(buf," \n}"); Insertstr(rlst->position, buf); /* Modify to take into account compartment sizes */ /* separate into scalars and vectors */ flag = 0; for (i = ncons; i < rlst->nsym; i++) { if (rlst->capacity[i][0]) { if (!(rlst->symorder[i]->subtype & ARRAY)) { if (! flag) { flag = 1; qv = insertstr(rlst->position, ""); #if 0 && VECTORIZE vectorize_substitute(qv, instance_loop()); #endif } Sprintf(buf, "\n_RHS%d(%d) *= %s", fun->u.i, rlst->symorder[i]->varnum, rlst->capacity[i]); Insertstr(rlst->position, buf); Sprintf(buf, ";\n_MATELM%d(%d, %d) *= %s;", fun->u.i, rlst->symorder[i]->varnum, rlst->symorder[i]->varnum, rlst->capacity[i]); Insertstr(rlst->position, buf); } } } if (flag) { qv = insertstr(rlst->position, ""); #if 0 && VECTORIZE vectorize_substitute(qv, " } /* ILOOPEND */\n"); #endif } for (i = ncons; i < rlst->nsym; i++) { if (rlst->capacity[i][0]) { if (rlst->symorder[i]->subtype & ARRAY) { Sprintf(buf, "\nfor (_i=0; _i < %d; _i++) {\n", rlst->symorder[i]->araydim); Insertstr(rlst->position, buf); qv = insertstr(rlst->position, ""); #if 0 && VECTORIZE vectorize_substitute(qv, instance_loop()); #endif Sprintf(buf," _RHS%d(_i + %d) *= %s", fun->u.i, rlst->symorder[i]->varnum, rlst->capacity[i]); Insertstr(rlst->position, buf); Sprintf(buf, ";\n_MATELM%d(_i + %d, _i + %d) *= %s;", fun->u.i, rlst->symorder[i]->varnum, rlst->symorder[i]->varnum, rlst->capacity[i]); Insertstr(rlst->position, buf); qv = insertstr(rlst->position, ""); #if 0 && VECTORIZE vectorize_substitute(qv, " } /* ILOOPEND */\n"); #endif Insertstr(rlst->position, "}"); } } } /*----------*/ Insertstr(rlst->position, "}\n"); linmat = 1; for (r1=rlst->reaction; r1; r1 = r1->reactnext) { NOT_CVODE_FLAG { genderivterms(r1, 1, fun->u.i); } genmatterms(r1, fun->u.i); } NOT_CVODE_FLAG { /* to end of function */ for (i = 0, r1=clst->reaction; r1; r1 = r1->reactnext) { i = genconservterms(i, r1, fun->u.i, rlst); } if (firsttrans1) { Sprintf(buf, "\n#define _linmat%d %d\n", fun->u.i, linmat); Linsertstr(procfunc, buf); } if (firsttrans) { kinlist(fun, rlst); #if 0 && VECTORIZE if (vectorize) { Sprintf(buf, "static _vector_%s();\n", fun->name); qv = linsertstr(procfunc, ""); vectorize_substitute(qv, buf); } #endif if (strcmp(mname, "_advance") == 0) { /* use for simeq */ Sprintf(buf, "\n#define _RHS%d(arg) _coef%d[arg][%d]\n", fun->u.i, fun->u.i, nstate); Linsertstr(procfunc, buf); Sprintf(buf, "\n#define _MATELM%d(arg1,arg2) _coef%d[arg1][arg2]\n", fun->u.i, fun->u.i); Linsertstr(procfunc, buf); Sprintf(buf, "static double **_coef%d;\n", fun->u.i); Linsertstr(procfunc, buf); } else { /*for sparse matrix solver*/ /* boilerplate for using sparse matrix solver */ Sprintf(buf, "static double *_coef%d;\n", fun->u.i); qv = linsertstr(procfunc, buf); #if VECTORIZE vectorize_substitute(qv, ""); #endif Sprintf(buf, "\n#define _RHS%d(_arg) _coef%d[(_arg + 1)]\n", fun->u.i, fun->u.i); qv = linsertstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "\n#define _RHS%d(_arg) _rhs[(_arg+1)*_STRIDE]\n", fun->u.i); vectorize_substitute(qv, buf); #endif Sprintf(buf, "\n#define _MATELM%d(_row,_col)\ *(_getelm(_row + 1, _col + 1))\n", fun->u.i); qv = linsertstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "\n#define _MATELM%d(_row,_col) _nrn_thread_getelm((SparseObj*)_so, _row + 1, _col + 1, _iml)[_iml]\n", fun->u.i); vectorize_substitute(qv, buf); #endif {static int first = 1; if (first) { first = 0; }} } } } /* end of NOT_CVODE_FLAG */ } static void genmatterms(r, fn) Reaction *r; int fn; /*function number, numlist*/ { Symbol *s, *s1; Item *q; Rterm *rt, *rt1; int i, j, j1, n; if (r->rterm[1] == (Rterm *)0 && r->krate[1]) { return; /* no fluxes go into matrix */ } q = r->position; for (j=0; j < 2; j++) for (rt = r->rterm[j]; rt; rt = rt->rnext) {/*d/dstate*/ s = rt->sym; if (!(rt->isstate)) { continue; } /* construct the term */ Sprintf(buf, "_term = %s", r->krate[j]); Insertstr(q, buf); if (rt->num != 1) { Sprintf(buf, "* %d", rt->num); Insertstr(q, buf); } for (rt1 = r->rterm[j]; rt1; rt1 = rt1->rnext) { n = rt1->num; if (rt == rt1) { n--; } for (i=0; isym); if (rt1->str) { Sprintf(buf, "[%s]", rt1->str); Insertstr(q, buf); } } } Insertstr(q, ";\n"); /* put in each equation (row) */ for (j1=0; j1<2; j1++) for (rt1 = r->rterm[j1]; rt1; rt1=rt1->rnext) { s1 = rt1->sym; if (!(rt1->isstate)) { continue; } if (s1->varnum < ncons) continue; Sprintf(buf, "_MATELM%d(", fn); Insertstr(q, buf); if (rt1->str) { Sprintf(buf, "%d + %s", s1->varnum, rt1->str); Insertstr(q, buf); } else { Sprintf(buf, "%d", s1->varnum); Insertstr(q, buf); } if (rt->str) { Sprintf(buf, ",%d + %s)", s->varnum, rt->str); Insertstr(q, buf); } else { Sprintf(buf, ",%d)", s->varnum); Insertstr(q, buf); } if (j == j1) { Insertstr(q, " +="); }else{ Insertstr(q, " -="); } if (rt1->num != 1) { Sprintf(buf, "%d * ", rt1->num); Insertstr(q, buf); } Insertstr(q, "_term;\n"); } } /* REACTION comment left in */ } void massageconserve(q1, q3, q5) /* CONSERVE react '=' expr */ Item *q1, *q3, *q5; { /* the list of states is in rterm at this time with the first at the end */ Reaction *r1; Item* qv; r1 = conslist; conslist = (Reaction *)emalloc(sizeof(Reaction)); conslist->reactnext = r1; conslist->rterm[0] = rterm; conslist->rterm[1] = (Rterm *)0; conslist->krate[0] = qconcat(q3->next, q5); conslist->krate[1] = (char *)0; /*SUPPRESS 440*/ replacstr(q1, "/*"); qv = insertstr(q1, ""); #if 0 && VECTORIZE vectorize_substitute(qv, instance_loop()); #endif /*SUPPRESS 440*/ Insertstr(q5->next, "*/\n"); /*SUPPRESS 440*/ conslist->position = insertstr(q5->next->next, "/*CONSERVATION*/\n"); #if 0 && VECTORIZE vectorize_substitute(conslist->position, "/*CONSERVATION*/\n\ } /*ILOOPEND*/\n"); #endif rterm = (Rterm *)0; } static int genconservterms(eqnum, r, fn, rlst) Reaction *r; int eqnum, fn; /*function number*/ Rlist *rlst; { Item *q; Rterm *rt, *rtdiag; char eqstr[NRN_BUFSIZE]; q = r->position; /* find the term used for the equation number (important if array)*/ for (rtdiag = (Rterm *)0, rt = r->rterm[0]; rt; rt = rt->rnext) { if (eqnum == rt->sym->varnum) { rtdiag = rt; break; } } assert (rtdiag); if (rtdiag->str) { Sprintf(eqstr, "%d(%d + %s", fn, eqnum, rtdiag->str); eqnum += rtdiag->sym->araydim; /*SUPPRESS 622*/ assert(0); /*could ever work only in specialized circumstances when same conservation eqn used for all elements*/ } else { Sprintf(eqstr, "%d(%d", fn, eqnum); eqnum++; } Sprintf(buf, "_RHS%s) = %s;\n", eqstr, r->krate[0]); Insertstr(q, buf); for (rt = r->rterm[0]; rt; rt = rt->rnext) { char buf1[NRN_BUFSIZE]; if (rlst->capacity[rt->sym->used][0]) { Sprintf(buf1, " * %s", rlst->capacity[rt->sym->used]); } else { buf1[0] = '\0'; } if (!(rt->isstate)) { diag(rt->sym->name, ": only (solved) STATE are allowed in CONSERVE equations."); } if (rt->str) { if(rlst->capacity[rt->sym->used][0]) { Sprintf(buf, "_i = %s;\n", rt->str); Insertstr(q, buf); } Sprintf(buf, "_MATELM%s, %d + %s) = %d%s;\n", eqstr, rt->sym->varnum, rt->str, rt->num, buf1); Insertstr(q, buf); Sprintf(buf, "_RHS%s) -= %s[%s]%s", eqstr, rt->sym->name, rt->str, buf1); }else{ Sprintf(buf, "_MATELM%s, %d) = %d%s;\n", eqstr, rt->sym->varnum, rt->num, buf1); Insertstr(q, buf); Sprintf(buf, "_RHS%s) -= %s%s", eqstr, rt->sym->name, buf1); } Insertstr(q, buf); if (rt->num != 1) { Sprintf(buf, " * %d;\n", rt->num); Insertstr(q, buf); }else { Insertstr(q, ";\n"); } } return eqnum; } static int number_states(fun, prlst, pclst) Symbol *fun; Rlist **prlst, **pclst; { /* reaction list has the symorder and this info is put back in sym->varnum*/ /* also index of symorder goes into sym->used */ Rlist *rlst, *clst; Symbol *s; int i, istate; /*match fun with proper reaction list*/ clst = clist; for (rlst = rlist; rlst && (rlst->sym != fun); rlst = rlst->rlistnext) clst = clst->rlistnext; if (rlst == (Rlist *)0) { diag(fun->name, " doesn't exist"); } *prlst = rlst; *pclst = clst; /* Number the states. */ for (i=0, istate=0; insym; i++) { s = rlst->symorder[i]; s->varnum = istate; s->used = i; /* set back to 0 in kinlist */ if (s->subtype & ARRAY) { istate += s->araydim; }else{ istate++; } } ncons = rlst->ncons; if (fun->u.i >= MAXKINBLK) { diag("too many solve blocks", (char*)0); } nstate_[fun->u.i] = istate; return istate; } static void kinlist(fun, rlst) Symbol *fun; Rlist *rlst; { int i, count; Symbol *s; Item* qv; if (rlst->slist_decl) { return; } rlst->slist_decl = 1; /* put slist and dlist in initlist */ count = 0; for (i=0; i < rlst->nsym; i++) { s = rlst->symorder[i]; if (s->subtype & ARRAY) { int dim = s->araydim; count += dim; }else{ count++; } } Sprintf(buf, "\n _slist%d = (int*)malloc(sizeof(int)*%d);\n" " _dlist%d = (int*)malloc(sizeof(int)*%d);\n" , fun->u.i, count, fun->u.i, count); Lappendstr(initlist, buf); for (i=0; i < rlst->nsym; i++) { s = rlst->symorder[i]; #if CVODE slist_data(s, s->varnum, fun->u.i); #endif if (s->subtype & ARRAY) { int dim = s->araydim; Sprintf(buf, "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = (%s + _i) - _p;" ,dim, fun->u.i , s->varnum, s->name); qv = lappendstr(initlist, buf); #if 0 && VECTORIZE if (vectorize){ Sprintf(buf, "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = (%s + _i) - _p[_ix];" ,dim, fun->u.i , s->varnum, s->name); vectorize_substitute(qv, buf); } #endif Sprintf(buf, " _dlist%d[%d+_i] = (D%s + _i) - _p;}\n" , fun->u.i, s->varnum, s->name); qv = lappendstr(initlist, buf); #if 0 && VECTORIZE if (vectorize){ Sprintf(buf, " _dlist%d[%d+_i] = (D%s + _i) - _p[_ix];}\n" , fun->u.i, s->varnum, s->name); vectorize_substitute(qv, buf); } #endif }else{ Sprintf(buf, "_slist%d[%d] = &(%s) - _p;", fun->u.i, s->varnum, s->name); qv = lappendstr(initlist, buf); #if 0 && VECTORIZE if (vectorize){ Sprintf(buf, "_slist%d[%d] = &(%s) - _p[_ix];", fun->u.i, s->varnum, s->name); vectorize_substitute(qv, buf); } #endif Sprintf(buf, " _dlist%d[%d] = &(D%s) - _p;\n", fun->u.i, s->varnum, s->name); qv = lappendstr(initlist, buf); #if 0 && VECTORIZE if (vectorize){ Sprintf(buf, " _dlist%d[%d] = &(D%s) - _p[_ix];\n", fun->u.i, s->varnum, s->name); vectorize_substitute(qv, buf); } #endif } s->used = 0; } Sprintf(buf, "#pragma acc enter data copyin(_slist%d[0:%d])\n" " #pragma acc enter data copyin(_dlist%d[0:%d])\n\n" , fun->u.i, count, fun->u.i, count); Lappendstr(initlist, buf); } /* for now we only check CONSERVE and COMPARTMENT */ void check_block(standard, actual, mes) int standard, actual; char *mes; { if (standard != actual) { diag(mes, " not allowed in this kind of block"); } } /* Syntax to take into account compartment size compart: COMPARTMENT NAME ',' expr '{' namelist '}' {massagecompart($4, $5, $7, SYM($2));} | COMPARTMENT expr '{' namelist '}' {massagecompart($2, $3, $5, SYM0);} | COMPARTMENT error {myerr("Correct syntax is: \ COMPARTMENT index, expr { vectorstates }\n\ COMPARTMENT expr { scalarstates }");} ; */ /* implementation We save enough info here so that the rlist built in massagekinetic can point to compartment size expressions which are later used analogously to c*dv/dt and also affect the conservation equations. see Item ** Rlist->capacity[2] any index is replaced by _i. the name list is checked to make sure they are states compartlist is a list of triples of item pointers which holds the info for massagekinetic. */ void massagecompart(qexp, qb1, qb2, indx) Item *qexp, *qb1, *qb2; Symbol *indx; { Item *q, *qs; /* surround the statement with comments so that the expession will benignly exist for later use */ /*SUPPRESS 440*/ Insertstr(qb2->next, "*/\n"); if (indx) { for (q = qexp; q != qb1; q = q->next) { if (q->itemtype == SYMBOL && SYM(q) == indx) { replacstr(q, "_i"); } } /*SUPPRESS 440*/ Insertstr(qexp->prev->prev->prev, "/*"); }else{ /*SUPPRESS 440*/ Insertstr(qexp->prev, "/*"); } for (q = qb1->next; q != qb2; q = qs) { qs = q->next; if (!(SYM(q)->subtype & STAT) && in_solvefor(SYM(q))) { delete(q); #if 0 diag(SYM(q)->name, "must be a (solved) STATE in a COMPARTMENT statement"); #endif } } if (!compartlist) { compartlist = newlist(); } Lappenditem(compartlist, qexp); Lappenditem(compartlist, qb1); Lappenditem(compartlist, qb2); } void massageldifus(qexp, qb1, qb2, indx) Item *qexp, *qb1, *qb2; Symbol *indx; { Item *q, *qs, *q1; Symbol* s, *s2; /* surround the statement with comments so that the expession will benignly exist for later use */ /*SUPPRESS 440*/ Insertstr(qb2->next, "*/\n"); if (indx) { for (q = qexp; q != qb1; q = q->next) { if (q->itemtype == SYMBOL && SYM(q) == indx) { replacstr(q, "_i"); } } /*SUPPRESS 440*/ Insertstr(qexp->prev->prev->prev, "/*"); }else{ /*SUPPRESS 440*/ Insertstr(qexp->prev, "/*"); } if (!ldifuslist) { ldifuslist = newlist(); } for (q = qb1->next; q != qb2; q = qs) { qs = q->next; s = SYM(q); s2 = SYM0; if (!(s->subtype & STAT) && in_solvefor(s)) { delete(q); diag(SYM(q)->name, "must be a (solved) STATE in a LONGITUDINAL_DIFFUSION statement"); } lappendsym(ldifuslist, s); Lappenditem(ldifuslist, qexp); Lappenditem(ldifuslist, qb1); /* store the COMPARTMENT volume expression for this sym */ q1 = compartlist; if (q1) ITERATE(q1, compartlist) { Item *qexp, *qb1, *qb2, *q; qexp = ITM(q1); q1 = q1->next; qb1 = ITM(q1); q1 = q1->next; qb2 = ITM(q1); for (q = qb1; q != qb2; q = q->next) { if (q->itemtype == SYMBOL) { s2 = SYM(q); if (s == s2) break; } } if (s == s2) { lappenditem(ldifuslist, qexp); lappenditem(ldifuslist, qb1); break; } } if (s != s2) { diag(SYM(q)->name, "must be declared in COMPARTMENT"); } lappendstr(ldifuslist, "0"); /* will be flux conc index if any */ lappendstr(ldifuslist, ""); /* will be dflux/dconc if any */ } } static List* kvect; void kin_vect1(q1, q2, q4) Item *q1, *q2, *q4; { if (!kvect) { kvect = newlist(); } Lappenditem(kvect, q1); /* static .. */ Lappenditem(kvect, q2); /* sym */ Lappenditem(kvect, q4); /* } */ } void kin_vect2() { Item *q, *q1, *q2, *q4; return; if (kvect) { ITERATE(q, kvect) { q1 = ITM(q); q = q->next; q2 = ITM(q); q = q->next; q4 = ITM(q); kin_vect3(q1, q2, q4); } } } void kin_vect3(q1, q2, q4) Item *q1, *q2, *q4; { Symbol* fun; Item *q, *first, *last, *insertitem(); fun = SYM(q2); last = insertstr(q4->next, "\n"); first = insertstr(last, "\n/*copy of previous function */\n"); for (q = q1; q != q4->next; q = q->next) { if (q == q2) { Sprintf(buf, "_vector_%s", fun->name); insertstr(last, buf); }else{ insertitem(last, q); } } Sprintf(buf, "\n#undef WANT_PRAGMA\n#define WANT_PRAGMA 1\ \n#undef _INSTANCE_LOOP\n#define _INSTANCE_LOOP \ for (_ix = _base; _ix < _bound; ++_ix) "); insertstr(first, buf); Sprintf(buf, "\n#undef _RHS%d\n#define _RHS%d(arg) \ _coef%d[arg][_ix]\n", fun->u.i, fun->u.i, fun->u.i); insertstr(first, buf); Sprintf(buf, "\n#undef _MATELM%d\n#define _MATELM%d(row,col) \ _jacob%d[(row)*%d + (col)][_ix]\n", fun->u.i, fun->u.i, fun->u.i, nstate_[fun->u.i]); insertstr(first, buf); } static int astmt_state; static Item* astmt_last; void ostmt_start() { astmt_state = 0; } void see_ostmt() { #if 0 && VECTORIZE if (vectorize) { if (astmt_state) { astmt_state = 0; vectorize_substitute(astmt_last, "\n } /*ILOOPEND*/\n"); } } #endif } void see_astmt(q1, q2) Item *q1, *q2; { #if 0 && VECTORIZE Item* q; if (vectorize) { if (!astmt_state) { astmt_state = 1; q = insertstr(q1, ""); vectorize_substitute(q, instance_loop()); } astmt_last = insertstr(q2->next, ""); } #endif } void vectorize_if_else_stmt(blocktype) int blocktype; { #if 0 && VECTORIZE if (blocktype == KINETIC && vectorize) { vectorize = 0; fprintf(stderr, "Notice: Can't vectorize a kinetic block if it contains\n\ an if...else... statement.\n"); } #endif } #if CVODE static void cvode_kin_remove() { Item* q, *q2; #if 0 prn(kin_items_, kin_items_->prev); prn(cvode_sbegin, cvode_send); #endif q2 = cvode_sbegin; ITERATE(q, kin_items_) { while (ITM(q) != q2) { assert(q2 != cvode_send); /* past the list */ q2 = q2->next; delete(q2->prev); } q2 = q2->next; } } void prn(q1,q2) Item *q1, *q2; { Item* qq, *q; for (qq = q1; qq != q2; qq=qq->next) { if (qq->itemtype == ITEM) { fprintf(stderr, "itm "); q = ITM(qq); }else{ q = qq; } switch(q->itemtype) { case STRING: fprintf(stderr, "%p STRING |%s|\n", q, STR(q)); break; case SYMBOL: fprintf(stderr, "%p SYMBOL |%s|\n", q, SYM(q)->name); break; case ITEM: fprintf(stderr, "%p ITEM\n", q); break; default: fprintf(stderr, "%p type %d\n", q, q->itemtype); break; } } } void cvode_kinetic(qsol, fun, numeqn, listnum) Item* qsol; Symbol* fun; int numeqn, listnum; { #if 1 Item* qn; int out; Item* q, *pbeg, *pend, *qnext; /* get a list of the original items so we can keep removing the added ones to get back to the original list. */ if (done_list) for (q = done_list->next; q != done_list; q = qn) { qn = q->next; if (SYM(q) == fun) { delete(q); } } kinetic_intmethod(fun, "NEURON's CVode"); Lappendstr(procfunc, "\n/*CVODE ode begin*/\n"); sprintf(buf, "static int _ode_spec%d() {_reset=0;{\n", fun->u.i); Lappendstr(procfunc, buf); sprintf(buf, "static int _ode_spec%d(_threadargsproto_) {int _reset=0;{\n", fun->u.i); vectorize_substitute(procfunc->prev, buf); copyitems(cvode_sbegin, cvode_send, procfunc->prev); Lappendstr(procfunc, "\n/*CVODE matsol*/\n"); sprintf(buf, "static int _ode_matsol%d() {_reset=0;{\n", fun->u.i); Lappendstr(procfunc, buf); sprintf(buf, "static int _ode_matsol%d(void* _so, double* _rhs, _threadargsproto_) {int _reset=0;{\n", fun->u.i); vectorize_substitute(procfunc->prev, buf); cvode_flag = 1; kinetic_implicit(fun, "dt", "ZZZ"); cvode_flag = 0; pbeg = procfunc->prev; copyitems(cvode_sbegin, cvode_send, procfunc->prev); pend = procfunc->prev; #if 1 /* remove statements containing f_flux or b_flux */ for (q = pbeg; q != pend; q = qnext) { qnext = q->next; if (q->itemtype == SYMBOL && (strcmp(SYM(q)->name, "f_flux") == 0 || strcmp(SYM(q)->name, "b_flux") == 0 )) { /* find the beginning of the statement */ out = 0; for (;;) { switch(q->itemtype) { case STRING: if (strchr(STR(q), ';')) { out = 1; } break; case SYMBOL: if (SYM(q)->name[0] == ';') { out = 1; } break; } if (out) { break; } q = q->prev; } q = q->next; /* delete the statement */ while (q->itemtype != SYMBOL || SYM(q)->name[0] != ';') { qnext = q->next; delete(q); q = qnext; } qnext = q->next; delete(q); } } #endif Lappendstr(procfunc, "\n/*CVODE end*/\n"); #endif } void single_channel(qsol, fun, numeqn, listnum) Item* qsol; Symbol* fun; int numeqn, listnum; { Rlist *rlst, *clst; int nstate, i; int out; Item* q, *pbeg, *pend, *qnext; Reaction* r1; return; nstate = number_states(fun, &rlst, &clst); for (r1 = rlst->reaction; r1; r1 = r1->reactnext) { if (!r1->rterm[0]) { /* printf("there is a flux\n");*/ return; } if (!r1->rterm[1]) { /* printf("there is a sink\n");*/ return; } for (i=0; i < 2; ++i) { if (r1->rterm[i]->rnext) { /* printf("The scheme is nonlinear\n");*/ return; } if (!r1->rterm[i]->isstate) { /* printf("reaction term is not a STATE\n");*/ return; } } } for (i=0; i < rlst->nsym; ++i) { if (rlst->capacity[i][0] != '\0') { /* printf("there are COMPARTMENT statements\n");*/ return; } } cvode_kin_remove(); for (r1 = rlst->reaction; r1; r1 = r1->reactnext) { for (i=0; i<2; ++i) { sprintf(buf, " _nrn_single_react(%d", r1->rterm[i]->sym->varnum); insertstr(r1->position, buf); if (r1->rterm[i]->str) { sprintf(buf, "+ %s", r1->rterm[i]->str); insertstr(r1->position, buf); } sprintf(buf, ",%d", r1->rterm[(i+1)%2]->sym->varnum); insertstr(r1->position, buf); if (r1->rterm[(i+1)%2]->str) { sprintf(buf, "+ %s", r1->rterm[(i+1)%2]->str); insertstr(r1->position, buf); } sprintf(buf, ", %s);\n", r1->krate[i]); insertstr(r1->position, buf); } } Lappendstr(procfunc, "\n/*Single Channel begin*/\n"); sprintf(buf, "static int _singlechan%d(_v, _pp, _ppd) double _v; double* _pp; Datum* _ppd;{\n\ _p = _pp; _ppvar = _ppd; v = _v; _reset=0;\n{\n", fun->u.i); Lappendstr(procfunc, buf); pbeg = procfunc->prev; copyitems(cvode_sbegin, cvode_send, procfunc->prev); pend = procfunc->prev; #if 1 /* remove statements containing f_flux or b_flux */ for (q = pbeg; q != pend; q = qnext) { qnext = q->next; if (q->itemtype == SYMBOL && (strcmp(SYM(q)->name, "f_flux") == 0 || strcmp(SYM(q)->name, "b_flux") == 0 )) { /* find the beginning of the statement */ out = 0; for (;;) { switch(q->itemtype) { case STRING: if (strchr(STR(q), ';')) { out = 1; } break; case SYMBOL: if (SYM(q)->name[0] == ';') { out = 1; } break; } if (out) { break; } q = q->prev; } q = q->next; /* delete the statement */ while (q->itemtype != SYMBOL || SYM(q)->name[0] != ';') { qnext = q->next; delete(q); q = qnext; } qnext = q->next; delete(q); } } #endif sprintf(buf, "\nstatic _singlechan_declare%d() {\n\ _singlechan_declare(_singlechan%d, _slist%d, %d);\n\ }\n", listnum, listnum, listnum, numeqn); Lappendstr(procfunc, buf); Lappendstr(procfunc, "\n/*Single Channel end*/\n"); cvode_kin_remove(); singlechan_=listnum; } #endif mod2c-8.2.2/src/mod2c_core/lex.l000077500000000000000000000107721425457616700163320ustar00rootroot00000000000000%{ /* /local/src/master/nrn/src/nmodl/lex.l,v 4.2 1997/11/05 17:59:02 hines Exp */ #include #include "nmodlconf.h" #undef output #undef unput #ifdef FLEX_SCANNER #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ { \ int c = Getc(); \ result = (c==EOF) ? YY_NULL : (buf[0]=c, 1); \ } #else #undef input #endif #include "modl.h" #include "parse1.h" #include "portability.h" int lexcontext = 0; extern int Getc(); extern int unGetc(); extern int unput(); #define debug(arg1,arg2) /*printf("lex:arg1|%s|\n", arg2);*/ %} D [0-9] E [Ee][-+]?{D}+ /* avoid unistd.h include which will define mkdir */ %option nounistd %% [a-zA-Z][a-zA-Z0-9_]*'+ { /*PRIME possibly high order*/ char *cp, buf[100]; int i; Symbol *base; /* count the primes and create SCoP name*/ cp = index(yytext, '\''); i = strlen(yytext) - (cp - yytext); *cp = '\0'; if (i > 1) { Sprintf(buf, "D%d%s", i, yytext); }else{ Sprintf(buf, "D%s", yytext); } /* determine if really a constant */ if ((i = input()) == '0') { Strcat(buf, "0"); yylval.qp = putintoken(buf, NAME); return NAME; }else{ unput(i); } /*create symbol if needed and store in intoken list*/ yylval.qp = putintoken(buf, PRIME); if (SYM(yylval.qp)->type != PRIME) { diag(yytext, " needed as derivative variable"); #if LINT goto yyfussy; #endif } /* the high order prime might not be explicitly declared at this time. But the base state may be an array. If it is, then make the PRIME an array of the same dimension. */ if ((base = lookup(yytext))) { if (base->subtype & ARRAY) { SYM(yylval.qp)->subtype |= ARRAY; SYM(yylval.qp)->araydim = base->araydim; } } return PRIME; } WHILE | IF | ELSE { /* translate to lower case */ char *cp; for (cp = yytext; *cp; cp++) { *cp += 'a' - 'A'; } yylval.qp = putintoken(yytext, NAME); return SYM(yylval.qp)->type; } [a-zA-Z][a-zA-Z0-9_]* { /*NAME*/ Symbol *s; yylval.qp = putintoken(yytext, NAME); s = SYM(yylval.qp); if (s->type == PRIME) diag(yytext, " being used as derivative variable"); return s->type; } {D}+ { /*INTEGER*/ yylval.qp = putintoken(yytext, INTEGER); /* Numbers are not looked for */ return INTEGER; } {D}+"."{D}*({E})? | {D}*"."{D}+({E})? | {D}+{E} { /*REAL*/ yylval.qp = putintoken(yytext, REAL); /* Numbers are not looked for */ return REAL; } \"[^\"]*\" { /* STRING */ yylval.qp = putintoken(yytext, STRING); return STRING; /* can't quote \" */ } \> { yylval.qp = putintoken(yytext, 0); return GT;} \>= { yylval.qp = putintoken(yytext, 0); return GE;} \< { yylval.qp = putintoken(yytext, 0); return LT;} \<= { yylval.qp = putintoken(yytext, 0); return LE;} == { yylval.qp = putintoken(yytext, 0); return EQ;} != { yylval.qp = putintoken(yytext, 0); return NE;} ! { yylval.qp = putintoken(yytext, 0); return NOT;} \&\& { yylval.qp = putintoken(yytext, 0); return AND;} \|\| { yylval.qp = putintoken(yytext, 0); return OR;} \<-\> { yylval.qp = putintoken(yytext, 0); return REACT1;} \~\+ { /* syntactic sugar for equation addition */ yylval.qp = putintoken(yytext, 0); if (lexcontext == NONLINEAR) return NONLIN1; if (lexcontext == LINEAR) return LIN1; diag("equation addition can't occur in this type of block", (char *)0); } \~ { /* syntactic sugar for equations */ yylval.qp = putintoken(yytext, 0); if (lexcontext == NONLINEAR) return NONLIN1; if (lexcontext == LINEAR) return LIN1; if (lexcontext == PARTIAL) return yytext[0]; if (lexcontext == KINETIC) return REACTION; diag("equations can't occur in this type of block", (char *)0); } [ \t] {/*ignore spacing characters*/;} \r\n {/*ignore newline*/} \r {/*ignore newline*/} \n {/*ignore newline*/} :.* {/*ignore inline comments*/;} \?.* {/*ignore inline comments*/;} \{ { yylval.qp = putintoken("{", 0); return yytext[0]; } \} { yylval.qp = putintoken("}", 0); return yytext[0]; } . { yylval.qp = putintoken(yytext, 0); return yytext[0]; } %% #ifndef FLEX_SCANNER int input() { int c; c = Getc(); if (c == EOF) { c = 0; } return c; } #endif int unput(c) int c; { return unGetc(c); } int output(c) int c; { #if LINT IGNORE(c); #endif diag("internal error: ", "called output"); return 0; } int yywrap() { return 1; } char * inputtopar() { /* returns string up to and not including * next closing parenthesis */ /* main usage is to read the units string */ char *cp; int c; cp = buf; while ((c = input()) != ')' && c != '\n' && c != 0) { *cp++ = c; } if (c != ')') diag("Syntax error:", " no closing ')'"); *cp = '\0'; unput(c); return stralloc(buf, (char *) 0); } mod2c-8.2.2/src/mod2c_core/list.c000066400000000000000000000205631425457616700165000ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/list.c,v 4.2 1998/01/22 18:50:32 hines Exp */ /* list.c,v * Revision 4.2 1998/01/22 18:50:32 hines * allow stralloc with null string (creates empty string) * * Revision 4.1 1997/08/30 20:45:25 hines * cvs problem with branches. Latest nmodl stuff should now be a top level * * Revision 4.0.1.1 1997/08/08 17:23:50 hines * nocmodl version 4.0.1 * * Revision 4.0 1997/08/08 17:06:16 hines * proper nocmodl version number * * Revision 1.1.1.1 1994/10/12 17:21:35 hines * NEURON 3.0 distribution * * Revision 9.159 93/02/11 16:55:37 hines * minor mods for NeXT * * Revision 9.78 90/12/10 16:56:39 hines * TABLE allowed in FUNCTION and PROCEDURE * * Revision 9.76 90/12/07 09:27:14 hines * new list structure that uses unions instead of void *element * * Revision 8.1 89/09/29 16:26:03 mlh * ifdef for VMS and SYSV and some fixing of assert * * Revision 8.0 89/09/22 17:26:18 nfh * Freezing * * Revision 7.1 89/09/05 08:07:12 mlh * lappenditem() for use with lists of items which point to items * ITM(q) analogous to SYM(q) * * Revision 7.0 89/08/30 13:31:47 nfh * Rev 7 is now Experimental; Rev 6 is Testing * * Revision 6.0 89/08/14 16:26:30 nfh * Rev 6.0 is latest of 4.x; now the Experimental version * * Revision 4.1 89/08/07 15:34:30 mlh * freelist now takes pointer to list pointer and 0's the list pointer. * Not doing this is a bug for multiple sens blocks, etc. * * Revision 4.0 89/07/24 17:02:57 nfh * Freezing rev 3. Rev 4 is now Experimental * * Revision 3.1 89/07/07 16:54:16 mlh * FIRST LAST START in independent SWEEP higher order derivatives * * Revision 1.1 89/07/06 14:49:26 mlh * Initial revision * */ /* The following routines support the concept of a list. That is, one can insert at the head of a list or append to the tail of a list with linsert() and lappend(). In addition, one can insert an item before a known item and it will be placed in the proper list. Items point to strings, symbols, etc. Note that more than one item in the same or several lists can point to the same string, symbol. Finally, knowing an item, one can determine the preceding and following items with next() and prev(). Deletion, replacement and moving blocks of items is also supported. */ /* Implementation The list is a doubly linked list. A special item with element 0 is always at the tail of the list and is denoted as the List pointer itself. list->next point to the first item in the list and list->prev points to the last item in the list. i.e. the list is circular Note that in an empty list next and prev points to itself. It is intended that this implementation be hidden from the user via the following function calls. */ #include #include "modl.h" #include "parse1.h" static Item *newitem() { return (Item *)emalloc(sizeof(Item)); } List *newlist() { Item *i; i = newitem(); i->prev = i; i->next = i; i->element.lst = (List *)0; i->itemtype = 0; return (List *)i; } void freelist(plist) /*free the list but not the elements*/ List **plist; { Item *i1, *i2; if (!(*plist)) { return; } for (i1 = (*plist)->next; i1 != *plist; i1 = i2) { i2 = i1->next; Free(i1); } Free(*plist); *plist = (List *)0; } static Item *linkitem(item) Item *item; { Item *i; i = newitem(); i->prev = item->prev; i->next = item; item->prev = i; i->prev->next = i; return i; } #if 0 /*currently unused*/ Item *next(item) Item *item; { assert(item->next->element.lst); /* never return the list item */ return item->next; } Item *prev(item) Item *item; { assert(item->prev->element.lst); /* never return the list item */ return item->prev; } #endif Item *insertstr(item, str) /* insert a copy of the string before item */ /* a copy is made because strings are often assembled into a reusable buffer*/ Item *item; char *str; { Item *i; i = linkitem(item); i->element.str = stralloc(str, (char *)0); i->itemtype = STRING; return i; } Item *insertitem(item, itm) /* insert a item pointer before item */ Item *item, *itm; { Item *i; i = linkitem(item); i->element.itm = itm; i->itemtype = ITEM; return i; } Item *insertlist(item, lst) /* insert a item pointer before item */ Item *item; List *lst; { Item *i; i = linkitem(item); i->element.lst = lst; i->itemtype = LIST; return i; } Item *insertsym(item, sym) /* insert a symbol before item */ /* a copy is not made because we need the same symbol in different lists */ Item *item; Symbol *sym; { Item *i; i = linkitem(item); i->element.sym = sym; i->itemtype = SYMBOL; return i; } Item *linsertstr(list, str) List *list; char *str; { return insertstr(list->next, str); } Item *lappendstr(list, str) List *list; char *str; { return insertstr(list, str); } Item *linsertsym(list, sym) List *list; Symbol *sym; { return insertsym(list->next, sym); } Item *lappendsym(list, sym) List *list; Symbol *sym; { return insertsym(list, sym); } Item *lappenditem(list, item) List *list; Item *item; { return insertitem(list, item); } Item *lappendlst(list, lst) List *list, *lst; { return insertlist(list, lst); } void delete(item) Item *item; { assert(item->itemtype); /* can't delete list */ item->next->prev = item->prev; item->prev->next = item->next; Free(item); } char *emalloc(n) unsigned n; { /* check return from malloc */ char *p; p = malloc(n); if (p == (char *)0) { diag("out of memory", (char *)0); } return p; } char *stralloc(buf, rel) char *buf,*rel; { /* allocate space, copy buf, and free rel */ char *s; if (buf) { s = emalloc((unsigned)(strlen(buf) + 1)); Strcpy(s, buf); }else{ s = emalloc(1); s[0] = '\0'; } if (rel) { Free(rel); } return s; } void deltokens(q1, q2) /* delete tokens from q1 to q2 */ Item *q1, *q2; { /* It is a serious error if q2 precedes q1 */ Item *q; for (q = q1; q != q2;) { q = q->next; delete(q->prev); } delete(q2); } void move(q1, q2, q3) /* move q1 to q2 and insert before q3*/ Item *q1, *q2, *q3; { /* it is a serious error if q2 precedes q1 */ assert(q1 && q2); assert(q1->itemtype && q2->itemtype); q1->prev->next = q2->next; /* remove from first list */ q2->next->prev = q1->prev; q1->prev = q3->prev; q3->prev->next = q1; q3->prev = q2; q2->next = q3; } void movelist(q1, q2, s) /* move q1 to q2 from old list to end of list s*/ Item *q1, *q2; List *s; { move(q1, q2, s); } void replacstr(q, s) Item *q; char *s; { q->itemtype = STRING; q->element.str = stralloc(s, (char *)0); } Item *putintoken(s, type) char *s; short type; { /* make sure a symbol exists for s and append to intoken list */ Symbol *sym; if (s == (char *)0) diag("internal error"," in putintoken"); switch (type) { case STRING: case REAL: case INTEGER: return insertstr(intoken, s); default: if ((sym = lookup(s)) == SYM0) { sym = install(s, type); } break; } return insertsym(intoken, sym); } mod2c-8.2.2/src/mod2c_core/macnmodl.h000077500000000000000000000004321425457616700173200ustar00rootroot00000000000000#pragma precompile_target "nmodl_def.h" #define MSL_USE_PRECOMPILED_HEADERS 1 #include #include #include #include #pragma once off #define SYSV 1 #define MAC 1 #define NMODL 1 #define NOCMODL 1 #define VECTORIZE 1 #define CVODE 1 mod2c-8.2.2/src/mod2c_core/modl.c000066400000000000000000000167031425457616700164610ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ /* * int main(int argc, char *argv[]) --- returns 0 if translation is * successful. Diag will exit with 1 if error. * * ---The overall strategy of the translation consists of three phases. * * 1) read in the whole file as a sequence of tokens, parsing as we go. Most of * the trivial C translation such as appending ';' to statements is performed * in this phase as is the creation of the symbol table. Item lists maintain * the proper token order. Ater a whole block is read in, nontrivial * manipulation may be performed on the entire block. * * 2) Some blocks and statements can be manipulated only after the entire file * has been read in. The solve statement is an example since it can be * analysed only after we know what is the type of the associated block. The * kinetic block is another example whose translation depends on the SOLVE * method and so cannot be processed until the whole input file has been * read. * * 3) Output the lists. * */ #include "nmodlconf.h" #include #include #include #include "modl.h" FILE* fin; /* input file descriptor for filename.mod */ FILE* fcout; /* output file descriptor for filename.c */ char* finname; char* modprefix; static struct option long_options[] = { {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"outdir", required_argument, 0, 'o'}, {0,0,0,0} }; #if LINT char* clint; int ilint; Item* qlint; #endif #if NMODL && VECTORIZE extern int vectorize; extern int numlist; extern char* nmodl_version_; extern int usederivstatearray; #endif extern int yyparse(); extern int mkdir_p(); static void openfiles(char* given_filename, char* output_dir) { char output_filename [NRN_BUFSIZE]; char input_filename [NRN_BUFSIZE]; modprefix = strdup (given_filename); // we want to keep original string to open input file char* first_ext_char = strrchr(modprefix, '.'); // find last '.' that delimit file name from extension Sprintf(input_filename, "%s", given_filename); if(first_ext_char) *first_ext_char = '\0'; // effectively cut the extension from prefix if it exist in given_filename if ((fin = fopen(input_filename, "r")) == (FILE *) 0) { // first try to open given_filename Sprintf(input_filename, "%s.mod", given_filename); // if it dont work try to add ".mod" extension and retry Sprintf(finname, "%s.mod", given_filename); // finname is still a global variable, so we need to update it if ((fin = fopen(input_filename, "r")) == (FILE *) 0) { diag("Can't open input file: ", input_filename); } } if (output_dir) { if(mkdir_p(output_dir) != 0) { fprintf(stderr, "Can't create output directory %s\n", output_dir); exit(1); } char* basename = strrchr(modprefix,'/'); if (basename) { Sprintf(output_filename, "%s%s.cpp", output_dir, basename); } else { Sprintf(output_filename, "%s%s.cpp", output_dir, modprefix); } } else Sprintf(output_filename, "%s.cpp", modprefix); if ((fcout = fopen(output_filename, "w")) == (FILE *) 0) { diag("Can't create C file: ", output_filename); } Fprintf(stderr, "Translating %s into %s\n", input_filename, output_filename); } static void show_options(char** argv) { fprintf(stderr, "Source to source compiler from NMODL to C\n"); fprintf(stderr, "Usage: %s [options] Inputfile\n", argv[0]); fprintf(stderr, "Options:\n"); fprintf(stderr, "\t-o | --outdir directory where output files will be written\n"); fprintf(stderr, "\t-h | --help print this message\n"); fprintf(stderr, "\t-v | --version print version number\n"); } int main(int argc, char** argv) { int option = -1; int option_index = 0; char* output_dir = NULL; if (argc < 2) { show_options(argv); exit(1); } while ( (option = getopt_long (argc, argv, ":vho:", long_options, &option_index)) != -1) { switch (option) { case 'v': printf("%s\n", nmodl_version_); exit(0); case 'o': output_dir = strdup(optarg); break; case 'h': show_options(argv); exit(0); case ':': fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0], optopt); exit (-1); case '?': default: fprintf(stderr, "%s: invalid option `-%c' \n", argv[0], optopt); exit (-1); } } if ((argc - optind) > 1) { fprintf(stderr, "%s: Warning several input files specified on command line but only one will be processed\n", argv[0]); } init(); /* keywords into symbol table, initialize lists, etc. */ finname = argv[optind]; openfiles(finname, output_dir); /* .mrg else .mod, .var, .c */ IGNORE(yyparse()); /* * At this point all blocks are fully processed except the kinetic * block and the solve statements. Even in these cases the * processing doesn't involve syntax since the information is * held in intermediate lists of specific structure. * */ /* * go through the list of solve statements and construct the model() * code */ solvhandler(); /* * NAME's can be used in many cases before they were declared and * no checking up to this point has been done to make sure that * names have been used in only one way. * */ consistency(); chk_thread_safe(); parout(); c_out(); /* print .c file */ IGNORE(fclose(fcout)); #if NMODL && VECTORIZE if (vectorize) { Fprintf(stderr, "Thread Safe\n"); } if (usederivstatearray) { fprintf(stderr, "Derivatives of STATE array variables are not translated correctly and compile time errors will be generated.\n"); fprintf(stderr, " %s.c file may be manually edited to fix these errors.\n", modprefix); } #endif #if LINT { /* for lex */ extern int yytchar, yylineno; extern FILE *yyin; IGNORE(yyin); IGNORE(yytchar); IGNORE(yylineno); IGNORE(yyinput()); yyunput(ilint); yyoutput(ilint); } #endif return 0; } mod2c-8.2.2/src/mod2c_core/modl.h000077500000000000000000000243021425457616700164630ustar00rootroot00000000000000 #include #if HAVE_STRING_H #include #else #include #endif #include /*- The central data structure throughout modl is the list. Items can be inserted before a known item, inserted at the head of a list, or appended to the tail of a list. Items can be removed from a list. Lists can contain mixed types of items. Often an item which was an input token is edited and replaced by a string. The main types of items are strings and symbols. Lists used are: intoken Everytime the lexical analyser reads an input token it is placed in this list. Much translation to C takes place during parsing and most of that editing is done in this list. After an entire block is processed, the tokens are moved as a group to another list. initfunc main body of initmodel() from INITIAL. Automatic statements of the form state = state0 are constructed here. constructorfunc statements added to tail of allocation function destructorfunc statements executed when POINT_PROCESS destroyed termfunc main body of terminal() from TERMINAL modelfunc main body of model() from EQUATION. SOLVE statements in the equation block get expanded in this list procfunc all remaining blocks get concatenated to this list. It also gets the declarations. By prepending to procfunc, one can guarantee that a declaration precedes usage. initlist automatically generated statements that are to be executed only once are constructed here. Contains setup of slist's and dist's, etc. i.e. setup of indirect pointer lists to state groups. Other lists (not global) but used in several files are: symlist[] symbol table. One list for every beginning ascii character. see symbol.c and symbol.h. See the Symbol structure below. symlistlist for a stack of local symbol lists for LOCAL variables. Local variable 'name' is translated as _lname so that there can be no conflict with the 'p' array. syminorder Maintains order of variable declarations in the input file. Used to get good order in the .var file. firstlist Statements that must appear before anything else in the .c file. The only usage at this time is declaration of LOCAL variables outside of blocks. plotlist variables to be plotted on first entry to scop Other lists used for local or very specific purposes are: indeplist Independent variable info. parmlist parameters in a SENS statement statelist states used in a block containing a SENS statement sensinfo see sens.c senstmt see sens.c solvq Item location and method stored when SOLVE statement occurs. Solve statements are processed after all input is read. eqnq Linear equations assembled using this list. Kinetic.c should be modified to make uniform use of List's instead of special structures for Reaction, Rlist, etc. */ /* For char buffers that might be called on to hold long path names */ /* Note that paths can exceed MAX_PATH from on some systems */ #define NRN_BUFSIZE 8192 #include #if MAX_PATH > NRN_BUFSIZE #undef NRN_BUFSIZE #define NRN_BUFSIZE MAX_PATH #endif typedef struct Item List; /* list of mixed items */ typedef struct Item { short itemtype; union { struct Item *itm; List *lst; char *str; struct Symbol *sym; } element; /* pointer to the actual item */ struct Item *next; struct Item *prev; } Item; #define ITEM0 (Item *)0 #define LIST0 (List *)0 #define ITERATE(itm,lst) for (itm = (lst)->next; itm != (lst); itm = itm->next) /*- The symbol structure gives info about tokens. Not all tokens need all elements. Eg. the STRING uses only type and name. Much storage could be saved and much greater clarity could be attained if each type had its own sub stucture. Currently many of the structure elements serve very different purposes depending on the type. The following is a list of the current element usage: type token number from parse1.y subtype see definitions below u.i integration method - flag for variable step equation block - function number for generating variables u.str scop variables - max,min,units for .var file used state variable - temporary flag that it is used in an equation equation block - number of state variables used (# unknowns) in parout.c - the numeric order in the .var file. Generated and used in parout.c for the plotlist. usage a token is used as a variable (DEP) or function (FUNC) Another field, EXPLICIT_DECL, is used to determine if a variable appears in the input file or is automatically created, thus helping to organize the .var file. araydim arrays - dimension discdim discrete variable - dimension varnum state variable - during processing of a block containing equations in which simultaneous equations result; column number of state variable in the matrix. level lowest submodel level number for declarations of this symbol. Used for parameters ( in explicit_decl()). The default value is 100. name token name */ typedef struct Symbol { short type; long subtype; #if NMODL short nrntype; short assigned_to_; int no_threadargs; /* introduced for FUNCTION_TABLE table_name */ #if CVODE int* slist_info_; /* blunt instrument for retrieving ion concentration slist value */ #endif int ioncount_; /* ppvar index for ions */ #endif union { int i; char *str; } u; int used; int usage; int araydim; int discdim; int varnum; /* column number of state variable in * equations */ short level; char *name; } Symbol; #define SYM0 (Symbol *)0 /* * this is convenient way to get the element pointer if you know what type * the item is */ #define SYM(q) ((q)->element.sym) #define STR(q) ((q)->element.str) #define ITM(q) ((q)->element.itm) #define LST(q) ((q)->element.lst) /* types not defined in parser */ #define SPECIAL 1 #define SYMBOL 1 #define ITEM 2 #define LIST 3 /* * An item type, STRING is also used as an item type * An item type, VERBATIM is also used as an item type which is to be * treated the same as a STRING but with no prepended space on output. */ /* subtypes */ #define KEYWORD 01 #define PARM 02 #define INDEP 04 #define DEP 010 /* also in usage field */ #define STAT 020 #define ARRAY 040 #define FUNCT 0100 /* also in usage field */ #define PROCED 0200 #define NEGATIVE 0400 #define SEMI 01 /* ";" */ #define BEGINBLK 02 /* "{" */ #define ENDBLK 04 /* "}" */ #define DERF 01000 #define KINF 02000 #define NLINF 04000 #define DISCF 010000 #define STEP1 020000 #define PARF 040000 #define EXTDEF 0100000 #define LINF 0200000 #define UNITDEF 0400000L #define EXTDEF2 01000000L /* functions that can take array or function name arguments */ #define nmodlCONST 02000000L /* constants that do not appear in .var file */ #define EXTDEF3 04000000L /* get two extra reset arguments at beginning */ #define INTGER 010000000L /* must be cast to double in expr */ #define EXTDEF4 020000000L /* get extra NrnThread* arg at beginning */ #define EXTDEF5 040000000L /* not threadsafe from the extdef list */ #define EXPLICIT_DECL 01 /* usage field, variable occurs in input file */ extern char *emalloc(), /* malloc with out of space checking */ *stralloc(), /* copies string to new space */ *inputline(), /* used only by parser to get title line */ *inputtopar(), /* used only by parser to get units */ *Gets(); /* used only in io.c to get string from fin. */ #if 0 #if __TURBOC__ || SYSV || NeXT || LINUX #else extern char *sprintf(); #endif #endif extern List *newlist(), /* begins new empty list */ *inputtext(); /* used by parser to get block text from * VERBATIM and COMMENT */ extern Item *putintoken(), /* construct symbol and store input tokens */ *insertstr(), /* before a known Item */ *insertsym(), *linsertstr(), /* prepend to list */ *lappendstr(), /* append to list */ *linsertsym(), *lappendsym(), *lappenditem(), *lappendlst(), *next(), /* not used but should be instead of q->next */ *prev(); extern Symbol *install(), /* Install token in symbol table */ *lookup(), /* lookup name in symbol table */ *copylocal(), /* install LOCAL variable symbol */ *ifnew_parminstall(); /* new .var info only if * not already done. */ #include "nmodlfunc.h" extern char suffix[]; extern char* finname; /* the input file prefix */ extern char buf[]; /* general purpose temporary buffer */ extern char* modprefix; extern List *intoken, /* Main list of input tokens */ *initfunc, /* see discussion above */ *constructorfunc, *destructorfunc, *modelfunc, *termfunc, *procfunc, *initlist, *firstlist, *acc_present_list, *plotlist; extern FILE *fin, /* .mod input file descriptor */ *fcout; /* .c file */ extern Symbol *semi, /* ';'. When seen on output, causes newline */ *beginblk, /* '{'. Used for rudimentary indentation */ *endblk; /* on output. */ extern void printlist(List*); /* the following is to get lint to shut up */ #if LINT #undef assert #define assert(arg) {if (arg) ;} /* so fprintf doesn't give lint */ extern char *clint; extern int ilint; extern Item *qlint; #define Sprintf clint = sprintf #define Fprintf ilint = fprintf #define Fclose ilint = fclose #define Fflush ilint = fflush #define Printf ilint = printf #define Strcpy clint = strcpy #define Strcat clint = strcat #define Insertstr qlint = insertstr #define Insertsym qlint = insertsym #define Linsertsym qlint = linsertsym #define Linsertstr qlint = linsertstr #define Lappendsym qlint = lappendsym #define Lappendstr qlint = lappendstr #define Lappenditem qlint = lappenditem #define Lappendlst qlint = lappendlst #define IGNORE(arg) {if (arg);} #define Free(arg) free((char *)(arg)) #else #define Sprintf sprintf #define Fprintf fprintf #define Fclose fclose #define Fflush fflush #define Printf printf #define Strcpy strcpy #define Strcat strcat #define Insertstr insertstr #define Insertsym insertsym #define Linsertsym linsertsym #define Linsertstr linsertstr #define Lappendsym lappendsym #define Lappendstr lappendstr #define Lappenditem lappenditem #define Lappendlst lappendlst #define IGNORE(arg) arg #define Free(arg) free((void *)(arg)) #endif mod2c-8.2.2/src/mod2c_core/nmodlconf.h000066400000000000000000000240561425457616700175120ustar00rootroot00000000000000/* nmodlconf.h. Generated from nmodlconf.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ #ifndef H_nrnconf_included #define H_nrnconf_included 1 /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* define if using cygwin */ /* #undef CYGWIN */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* if mac os x */ /* #undef DARWIN */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_FENV_H 1 /* Define to 1 if you have the `fesetround' function. */ /* #undef HAVE_FESETROUND */ /* Define to 1 if you have the header file. */ #define HAVE_FLOAT_H 1 /* Define to 1 if you have the `ftime' function. */ #define HAVE_FTIME 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `gethostname' function. */ #define HAVE_GETHOSTNAME 1 /* Define to 1 if you have the `getpw' function. */ #define HAVE_GETPW 1 /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the `index' function. */ #define HAVE_INDEX 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `isatty' function. */ #define HAVE_ISATTY 1 /* define if using InterViews */ #define HAVE_IV 0 /* Define to 1 if you have the `imf' library (-limf). */ /* #undef HAVE_LIBIMF */ /* Define to 1 if you have the `m' library (-lm). */ /* #undef HAVE_LIBM */ /* Define to 1 if you have the `mass' library (-lmass). */ /* #undef HAVE_LIBMASS */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `lockf' function. */ #define HAVE_LOCKF 1 /* Define to 1 if you have the `mallinfo' function. */ #define HAVE_MALLINFO 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if you have the header file. */ #define HAVE_MATH_H 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkdir' function. */ #define HAVE_MKDIR 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* define if the compiler implements namespaces */ #define HAVE_NAMESPACES /**/ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the `posix_memalign' function. */ #define HAVE_POSIX_MEMALIGN 1 /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Define to 1 if you have the header file. */ #define HAVE_PTHREAD_H 1 /* Define to 1 if you have the `putenv' function. */ #define HAVE_PUTENV 1 /* Define to 1 if you have the `select' function. */ #define HAVE_SELECT 1 /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `setitimer' function. */ #define HAVE_SETITIMER 1 /* Define to 1 if you have the header file. */ #define HAVE_SGTTY_H 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* (Define if this signal exists) */ #define HAVE_SIGBUS 1 /* (Define if this signal exists) */ #define HAVE_SIGSEGV 1 /* define if the compiler has stringstream */ #define HAVE_SSTREAM /**/ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_STREAM_H */ /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STROPTS_H 1 /* Define to 1 if you have the `strstr' function. */ #define HAVE_STRSTR 1 /* Define to 1 if you have the `stty' function. */ /* #undef HAVE_STTY */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_CONF_H */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_DIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_FILE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have that is POSIX.1 compatible. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_TERMIO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the <_G_config.h> header file. */ #define HAVE__G_CONFIG_H 1 /* define if can declare inline float abs(float) */ #define INLINE_FLOAT_ABS 1 /* define if can declare inline long abs(long) */ #define INLINE_LONG_ABS 1 /* undefined or ::fabs or std::fabs */ #define IVOS_FABS ::fabs /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* define if using mingw */ /* #undef MINGW */ /* define if using Mike Neubig contributions */ /* #undef MikeNeubig */ /* where the lib hoc is */ #define NEURON_DATA_DIR "/usr/local/nrn/share/nrn" /* host triplet */ #define NRNHOST "x86_64-unknown-linux-gnu" /* cpu type consistent with nrnivmodl */ #define NRNHOSTCPU "x86_64" /* if 1 then dlopen nrnmech instead of special */ #define NRNMECH_DLL_STYLE 1 /* if nrnoc can use X11 */ #define NRNOC_X11 1 /* Name of package */ #define PACKAGE "nrn" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "nrn" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "nrn 7.4" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "nrn" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "7.4" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* define if RETSIGTYPE(*)(int) is not the prototype for a signal handler */ /* #undef SIGNAL_CAST */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define SUNDIALS data type 'realtype' as 'long double' */ #define SUNDIALS_DOUBLE_PRECISION 1 /* Use generic math functions */ #define SUNDIALS_USE_GENERIC_MATH 1 /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* Version number of package */ #define VERSION "7.4" /* define if no terminal capabilities */ /* #undef WITHOUT_MEMACS */ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN /* # undef WORDS_BIGENDIAN */ # endif #endif /* Define to 1 if the X Window System is missing or not being used. */ /* #undef X_DISPLAY_MISSING */ /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #define YYTEXT_POINTER 1 /* define if using Carbon libraries */ /* #undef carbon */ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef int64_t */ /* Define to `long int' if does not define. */ /* #undef off_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ #if defined(__cplusplus) #include #endif #if defined(CYGWIN) || defined(MINGW) #define WIN32 1 #endif #if defined(MINGW) #define CYGWIN #endif #endif /* H_nrnconf_included */ mod2c-8.2.2/src/mod2c_core/nmodlfunc.h000066400000000000000000000057061425457616700175210ustar00rootroot00000000000000int in_solvefor(); int cvode_cnexp_success(); void cvode_parse(); void Unit_push(); void unit_pop(); void unit_div(); void install_units(); void modl_units(); void vectorize_if_else_stmt(); void consistency(); void c_out(); void printlist(); void c_out_vectorize(); void vectorize_substitute(); void vectorize_do_substitute(); void solv_diffeq(); void add_deriv_imp_list(); void add_deriv_imp_really(); void deriv_used(); void massagederiv(); void matchinitial(); void matchbound(); void checkmatch(); void matchmassage(); void copyitems(); void disc_var_seen(); void massagediscblk(); void init_disc_vars(); void init(); void inblock(); void unGets(); void diag(); void enquextern(); void include_file(); void reactname(); void leftreact(); void massagereaction(); void flux(); void massagekinetic(); void fixrlst(); void kinetic_intmethod(); void genfluxterm(); void kinetic_implicit(); void massageconserve(); void check_block(); void massagecompart(); void massageldifus(); void kin_vect1(); void kin_vect2(); void kin_vect3(); void ostmt_start(); void see_astmt(); void see_ostmt(); void prn(); void cvode_kinetic(); void single_channel(); void freelist(); void delete(); void deltokens(); void move(); void movelist(); void replacstr(); void c_out(); void printitem(); void debugprintitem(); void printlist(); void c_out_vectorize(); void vectorize_substitute(); void vectorize_do_substitute(); void nrninit(); void parout(); void warn_ignore(); void ldifusreg(); void decode_ustr(); void units_reg(); void nrn_list(); void bablk(); void nrn_use(); void nrn_var_assigned(); void slist_data(); void out_nt_ml_frag(); void cvode_emit_interface(); void cvode_proced_emit(); void cvode_interface(); void cvode_valid(); void cvode_rw_cur(); void net_receive(); void net_init(); void fornetcon(); void chk_thread_safe(); void threadsafe_seen(); void explicit_decl(); void parm_array_install(); void parminstall(); void steppedinstall(); void indepinstall(); void depinstall(); void statdefault(); void vectorize_scan_for_func(); void defarg(); void lag_stmt(); void queue_stmt(); void add_reset_args(); void add_nrnthread_arg(); void check_tables(); void table_massage(); void hocfunchack(); void hocfunc(); void vectorize_use_func(); void function_table(); void watchstmt(); void threadsafe(); void nrnmutex(); void solv_partial(); void partial_eqn(); void massagepartial(); void partial_bndry(); void sensparm(); void add_sens_statelist(); void sensmassage(); void sens_nonlin_out(); void solv_nonlin(); void solv_lineq(); void eqnqueue(); void massagenonlin(); void init_linblk(); void init_lineq(); void lin_state_term(); void linterm(); void massage_linblk(); void solvequeue(); void solvhandler(); void save_dt(); void symbol_init(); void pushlocal(); void poplocal(); void conductance_hint(int blocktype, Item* q1, Item* q2); void possible_local_current(int blocktype, List* symlist); Symbol* breakpoint_current(Symbol* s); void nrnunit_dynamic_str(char* buf, const char* name, char* unit1, char* unit2); mod2c-8.2.2/src/mod2c_core/noccout.c000066400000000000000000000777601425457616700172120ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include #include "nmodlconf.h" /* print the .c file from the lists */ #include "modl.h" #include "parse1.h" #include "symbol.h" #define CACHEVEC 1 extern char* nmodl_version_; extern char* finname; #define P(arg) fputs(arg, fcout) List *procfunc, *initfunc, *modelfunc, *termfunc, *initlist, *firstlist; /* firstlist gets statements that must go before anything else */ #if NMODL List *nrnstate; extern List *currents, *set_ion_variables(), *get_ion_variables(); extern List *begin_dion_stmt(), *end_dion_stmt(); extern List* conductance_; extern List* breakpoint_local_current_; extern List* newtonspace_list; static void conductance_cout(); extern int net_send_buffer_in_initial; #endif extern Symbol *indepsym; extern List *indeplist; extern List *match_bound; extern List *defs_list; extern char *saveindep; char *modelline; extern int brkpnt_exists; extern int artificial_cell; extern int net_receive_; extern int net_send_seen_; extern int debugging_; extern int point_process; extern int artificial_cell; extern int derivimplic_listnum; #if CVODE extern Symbol* cvode_nrn_cur_solve_; extern Symbol* cvode_nrn_current_solve_; extern List* state_discon_list_; #endif #define NRN_INIT 0 #define NRN_JACOB 1 #define NRN_STATE 2 #define NRN_CUR 3 #define NRN_CUR_SYN 4 /* VECTORIZE has not been optional for years. We leave the define there but */ /* we no longer update the #else clauses. */ #if VECTORIZE extern int vectorize; static List *vectorize_replacements; /* pairs of item pointer, strings */ extern char* cray_pragma(); extern int electrode_current; /* 1 means we should watch out for extracellular and handle it correctly */ #endif #if __TURBOC__ || SYSV || VMS #define index strchr #endif static void initstates(); static void funcdec(); static void ext_vdef() { if (artificial_cell) { return; } if (electrode_current) { P("#if EXTRACELLULAR\n"); P(" _nd = _ml->_nodelist[_iml];\n"); P(" if (_nd->_extnode) {\n"); P(" _v = NODEV(_nd) +_nd->_extnode->_v[0];\n"); P(" }else\n"); P("#endif\n"); P(" {\n"); #if CACHEVEC == 0 P(" _v = NODEV(_nd);\n"); #else P(" _v = _vec_v[_nd_idx];\n _PRCELLSTATE_V\n"); #endif P(" }\n"); }else{ #if CACHEVEC == 0 P(" _nd = _ml->_nodelist[_iml];\n"); P(" _v = NODEV(_nd);\n"); #else P(" _v = _vec_v[_nd_idx];\n _PRCELLSTATE_V\n"); #endif } } static const char* print_fast_imem_code() { if (electrode_current) { if (point_process) { return "\n if (_nt->nrn_fast_imem) {\ \n _nt->nrn_fast_imem->nrn_sav_rhs[_nd_idx] += _vec_shadow_rhs[_iml];\ \n _nt->nrn_fast_imem->nrn_sav_d[_nd_idx] -= _vec_shadow_d[_iml];\ \n }"; } else { return "\n if (_nt->nrn_fast_imem) {\ \n _nt->nrn_fast_imem->nrn_sav_rhs[_nd_idx] += _rhs;\ \n _nt->nrn_fast_imem->nrn_sav_d[_nd_idx] -= _g;\ \n }"; } } else { return "\0"; } } static void rhs_d_pnt_race(const char* r, const char* d) { sprintf(buf, "\ \n\ \n#ifdef _OPENACC\ \n if(_nt->compute_gpu) {\ \n #pragma acc atomic update\ \n _vec_rhs[_nd_idx] %s _rhs;\ \n #pragma acc atomic update\ \n _vec_d[_nd_idx] %s _g;", r, d); P(buf); if(electrode_current) { sprintf(buf, "\ \n if (_nt->nrn_fast_imem) {\ \n #pragma acc atomic update\ \n _nt->nrn_fast_imem->nrn_sav_rhs[_nd_idx] %s _rhs;\ \n #pragma acc atomic update\ \n _nt->nrn_fast_imem->nrn_sav_d[_nd_idx] %s _g;\ \n }", r, d); P(buf); } sprintf(buf, "\ \n } else {\ \n _vec_shadow_rhs[_iml] = _rhs;\ \n _vec_shadow_d[_iml] = _g;\ \n }\ \n#else\ \n _vec_shadow_rhs[_iml] = _rhs;\ \n _vec_shadow_d[_iml] = _g;\ \n#endif\ \n }\ \n#ifdef _OPENACC\ \n if(!(_nt->compute_gpu)) { \ \n for (_iml = 0; _iml < _cntml_actual; ++_iml) {\ \n int _nd_idx = _ni[_iml];\ \n _vec_rhs[_nd_idx] %s _vec_shadow_rhs[_iml];\ \n _vec_d[_nd_idx] %s _vec_shadow_d[_iml];\ %s\ \n }\ \n#else\ \n for (_iml = 0; _iml < _cntml_actual; ++_iml) {\ \n int _nd_idx = _ni[_iml];\ \n _vec_rhs[_nd_idx] %s _vec_shadow_rhs[_iml];\ \n _vec_d[_nd_idx] %s _vec_shadow_d[_iml];\ %s\ \n#endif\ \n", r, d, print_fast_imem_code(), r, d, print_fast_imem_code()); P(buf); } /* when vectorize = 0 */ void c_out() { #if NMODL Item *q; extern int point_process; #endif Fprintf(fcout, "/* Created by Language version: %s */\n", nmodl_version_); Fflush(fcout); if (artificial_cell) { P("\n#undef DISABLE_OPENACC\n#define DISABLE_OPENACC\n\n"); } #if VECTORIZE if (vectorize) { vectorize_do_substitute(); kin_vect2(); /* heh, heh.. bet you can't guess what this is */ c_out_vectorize(); return; } #endif #if VECTORIZE fprintf(stderr, "Error : %s is not thread safe and incompatible with CoreNEURON\n" "See details at https://neuron.yale.edu/neuron/docs/multithread-parallelization", finname); abort(); P("/* NOT VECTORIZED */\n"); #endif Fflush(fcout); /* things which must go first and most declarations */ #if SIMSYS P("#include \n#include \n#include \n#include \"mathlib.h\"\n"); P("#include \"common.h\"\n#include \"softbus.h\"\n"); P("#include \"sbtypes.h\"\n#include \"Solver.h\"\n"); #else P("#include \n#include \n#include \n"); P("#undef PI\n"); #endif printlist(defs_list); printlist(firstlist); P("static int _reset;\n"); #if NMODL P("static "); #endif if (modelline) { Fprintf(fcout, "const char *modelname = \"%s\";\n\n", modelline); } else { Fprintf(fcout, "const char *modelname = \"\";\n\n"); } Fflush(fcout); /* on certain internal errors partial output * is helpful */ P("static int error;\n"); #if NMODL P("static "); #endif P("int _ninits = 0;\n"); P("static int _match_recurse=1;\n"); #if NMODL P("static void "); #endif P("_modl_cleanup(){ _match_recurse=1;}\n"); /* * many machinations are required to make the infinite number of * definitions involving _p in defs.h to be invisible to the user */ /* * This one allows scop variables in functions which do not have the * p array as an argument */ #if SIMSYS || HMODL || NMODL #else P("static double *_p;\n\n"); #endif funcdec(); Fflush(fcout); /* * translations of named blocks into functions, procedures, etc. Also * some special declarations used by some blocks */ printlist(procfunc); Fflush(fcout); /* Initialization function must always be present */ #if NMODL P("\nstatic void initmodel() {\n int _i; double _save;"); #endif #if SIMSYS || HMODL P("\ninitmodel() {\n int _i; double _save;"); #endif #if (!(SIMSYS || HMODL || NMODL)) P("\ninitmodel(_pp) double _pp[]; {\n int _i; double _save; _p = _pp;"); #endif #if !NMODL P("_initlists();\n"); #endif P("_ninits++;\n"); P(saveindep); /*see solve.c; blank if not a time dependent process*/ P("{\n"); initstates(); printlist(initfunc); if (match_bound) { P("\n_init_match(_save);"); } P("\n}\n}\n"); Fflush(fcout); #if NMODL /* generation of initmodel interface */ #if VECTORIZE P("\nstatic void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("double _v; int* _ni; int _iml, _cntml_padded, _cntml_actual;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); P("#endif\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n"); P(" _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n"); #else P("\nstatic nrn_init(_prop, _v) Prop *_prop; double _v; {\n"); P(" _p = _prop->param; _ppvar = _prop->dparam;\n"); #endif if (debugging_ && net_receive_) { P(" _tsav = -1e20;\n"); } if (!artificial_cell) {ext_vdef();} if (!artificial_cell) {P(" v = _v;\n");} printlist(get_ion_variables(1)); P(" initmodel();\n"); printlist(set_ion_variables(2)); #if VECTORIZE P("}}\n"); #else P("}\n"); #endif /* standard modl EQUATION without solve computes current */ P("\nstatic double _nrn_current(double _v){double _current=0.;v=_v;"); #if CVODE if (cvode_nrn_current_solve_) { fprintf(fcout, "if (cvode_active_) { %s(); }\n", cvode_nrn_current_solve_->name); } #endif P("{"); if (currents->next != currents) { printlist(modelfunc); } ITERATE(q, currents) { Sprintf(buf, " _current += %s;\n", SYM(q)->name); P(buf); } P("\n} return _current;\n}\n"); /* For the classic BREAKPOINT block, the neuron current also has to compute the dcurrent/dv as well as make sure all currents accumulated properly (currents list) */ if (brkpnt_exists) { P("\nstatic void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("int* _ni; double _rhs, _v; int _iml, _cntml_padded, _cntml_actual;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); P("#endif\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n"); P(" _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n"); ext_vdef(); if (currents->next != currents) { printlist(get_ion_variables(0)); #if CVODE cvode_rw_cur(buf); P(buf); } if (cvode_nrn_cur_solve_) { fprintf(fcout, "if (cvode_active_) { %s(); }\n", cvode_nrn_cur_solve_->name); } if (currents->next != currents) { #endif P(" _g = _nrn_current(_v + .001);\n"); printlist(begin_dion_stmt()); if (state_discon_list_) { P(" state_discon_flag_ = 1; _rhs = _nrn_current(_v); state_discon_flag_ = 0;\n"); }else{ P(" _rhs = _nrn_current(_v);\n"); } printlist(end_dion_stmt(".001")); P(" _g = (_g - _rhs)/.001;\n"); /* set the ion variable values */ printlist(set_ion_variables(0)); if (point_process) { P(" _g *= 1.e2/(_nd_area);\n"); P(" _rhs *= 1.e2/(_nd_area);\n"); } if (electrode_current) { #if CACHEVEC == 0 P(" NODERHS(_nd) += _rhs;\n"); #else P(" VEC_RHS(_ni[_iml]) += _rhs;\n"); #endif P("#if EXTRACELLULAR\n"); P(" if (_nd->_extnode) {\n"); P(" *_nd->_extnode->_rhs[0] += _rhs;\n"); P(" }\n"); P("#endif\n"); }else{ #if CACHEVEC == 0 P(" NODERHS(_nd) -= _rhs;\n"); #else P(" VEC_RHS(_ni[_iml]) -= _rhs;\n"); #endif } } P(" \n}}\n"); /* for the classic breakpoint block, nrn_cur computed the conductance, _g, and now the jacobian calculation merely returns that */ P("\nstatic void nrn_jacob(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("int* _ni; int _iml, _cntml_padded, _cntml_actual;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); P("#endif\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n"); P(" _p = _ml->_data + _iml*_psize;\n"); if (electrode_current) { #if CACHEVEC == 0 P(" NODED(_nd) -= _g;\n"); #else P(" VEC_D(_ni[_iml]) -= _g;\n"); #endif P("#if EXTRACELLULAR\n"); P(" if (_nd->_extnode) {\n"); P(" *_nd->_extnode->_d[0] += _g;\n"); P(" }\n"); P("#endif\n"); }else{ #if CACHEVEC == 0 P(" NODED(_nd) += _g;\n"); #else P(" VEC_D(_ni[_iml]) += _g;\n"); #endif } P(" \n}}\n"); } /* nrnstate list contains the EQUATION solve statement so this advances states by dt */ #if VECTORIZE P("\nstatic void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type){\n"); #else P("\nstatic nrn_state(_prop, _v) Prop *_prop; double _v; {\n"); #endif if (nrnstate || currents->next == currents) { #if VECTORIZE P("double _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); P("#endif\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n"); P(" _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n"); ext_vdef(); #else P(" _p = _prop->param; _ppvar = _prop->dparam;\n"); #endif P(" v=_v;\n _PRCELLSTATE_V\n{\n"); printlist(get_ion_variables(1)); if (nrnstate) { printlist(nrnstate); } if (currents->next == currents) { printlist(modelfunc); } printlist(set_ion_variables(1)); #if VECTORIZE P("}}\n"); #else P("}\n"); #endif } P("\n}\n"); #else /* Model function must always be present */ #if SIMSYS P("\nmodel() {\n"); P("double _break, _save;\n{\n"); #else P("\nmodel(_pp, _indepindex) double _pp[]; int _indepindex; {\n"); P("double _break, _save;"); #if HMODL P("\n{\n"); #else P("_p = _pp;\n{\n"); #endif #endif printlist(modelfunc); P("\n}\n}\n"); Fflush(fcout); #endif #if NMODL P("\nstatic void terminal(){}\n"); #else /* Terminal function must always be present */ #if SIMSYS || HMODL P("\nterminal() {"); P("\n{\n"); #else P("\nterminal(_pp) double _pp[];{"); P("_p = _pp;\n{\n"); #endif printlist(termfunc); P("\n}\n}\n"); Fflush(fcout); #endif /* initlists() is called once to setup slist and dlist pointers */ #if NMODL || SIMSYS || HMODL P("\nstatic void _initlists() {\n"); #else P("\n_initlists() {\n"); #endif P(" int _i; static int _first = 1;\n"); P(" int _cntml_actual=1;\n"); P(" int _cntml_padded=1;\n"); P(" int _iml=0;\n"); P(" if (!_first) return;\n"); printlist(initlist); P("_first = 0;\n}\n"); P(" } // namespace coreneuron\n"); } /* * One of the things initmodel() must do is initialize all states to the * value of state0. This generated code goes before any explicit initialize * code written by the user. */ static void initstates() { int i; Item *qs; Symbol *s; SYMITER_STAT { #if NMODL /* ioni and iono should not have initialization lines */ #define IONCONC 010000 if (s->nrntype & IONCONC) { continue; } #endif Sprintf(buf, "%s0", s->name); if (lookup(buf)) { /* if no constant associated * with a state such as the * ones automattically * generated by SENS then * there is no initialization * line */ if (s->subtype & ARRAY) { Fprintf(fcout, " for (_i=0; _i<%d; _i++) %s[_i] = %s0;\n", s->araydim, s->name, s->name); } else { Fprintf(fcout, " %s = %s0;\n", s->name, s->name); } } } } /* * here is the only place as of 18-apr-89 where we don't explicitly know the * type of a list element */ static int newline, indent; void printitem(q) Item* q; { if (q->itemtype == SYMBOL) { if (SYM(q)->type == SPECIAL) { switch (SYM(q)->subtype) { case SEMI: newline = 1; break; case BEGINBLK: newline = 1; indent++; break; case ENDBLK: newline = 1; indent--; break; } } Fprintf(fcout, " %s", SYM(q)->name); } else if (q->itemtype == VERBATIM) { Fprintf(fcout, "%s", STR(q)); } else if (q->itemtype == ITEM) { printitem(ITM(q)); }else { Fprintf(fcout, " %s", STR(q)); } } void debugprintitem(q) Item* q; { if (q->itemtype == SYMBOL) { printf("SYM %s\n", SYM(q)->name); } else if (q->itemtype == VERBATIM) { printf("VERB %s\n",STR(q)); } else if (q->itemtype == ITEM) { printf("ITM "); debugprintitem(ITM(q)); }else { printf("STR %s\n", STR(q)); } } void printlist(s) List *s; { Item *q; int i; newline = 0, indent = 0; /* * most of this is merely to decide where newlines and indentation * goes so that the .c file can be read if something goes wrong */ if (!s) { return; } ITERATE(q, s) { printitem(q); if (newline) { newline = 0; Fprintf(fcout, "\n"); for (i = 0; i < indent; i++) { Fprintf(fcout, " "); } } } } static void funcdec() { int i; Symbol *s; List *qs; int j, narg, more; SYMITER(NAME) { more = 0; /*EMPTY*/ /*maybe*/ if (s->subtype & FUNCT) { #define GLOBFUNCT 1 #if GLOBFUNCT && NMODL #else Fprintf(fcout, "static inline double %s(", s->name); more = 1; #endif } if (s->subtype & PROCED) { Fprintf(fcout, "static inline int %s(", s->name); more = 1; } if (more) { narg = s->varnum; if (vectorize) { if (narg) { Fprintf(fcout, "_threadargsprotocomma_ "); }else{ Fprintf(fcout, "_threadargsproto_"); } } /*loop over argcount and add ,double */ if (narg > 0) { Fprintf(fcout, "double"); } for (j=1; j < narg; ++j) { Fprintf(fcout, ", double"); } Fprintf(fcout,");\n"); } } } #if VECTORIZE /* when vectorize = 1 */ static void pr_layout_for_p(int ivdep, int fun_type) { /*no pointer chasing for ions, rhs, v and d */ P("double * _nt_data = _nt->_data;\n"); P("double * _vec_v = _nt->_actual_v;\n"); P("int stream_id = _nt->stream_id;\n"); if (fun_type == NRN_INIT) { P(" if (_nrn_skip_initmodel == 0) {\n"); } P("#if LAYOUT == 1 /*AoS*/\n"); P("for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n"); P(" _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n"); P("#elif LAYOUT == 0 /*SoA*/\n"); P(" _p = _ml->_data; _ppvar = _ml->_pdata;\n"); if (ivdep) { /* avoid auto-parallelization of nrn_init in artificial cell */ if(! (fun_type == NRN_INIT && artificial_cell) ) { P("/* insert compiler dependent ivdep like pragma */\n"); P("_PRAGMA_FOR_VECTOR_LOOP_\n"); } if(fun_type == NRN_INIT) P("_PRAGMA_FOR_INIT_ACC_LOOP_\n"); if(fun_type == NRN_STATE) P("_PRAGMA_FOR_STATE_ACC_LOOP_\n"); if(fun_type == NRN_CUR) P("_PRAGMA_FOR_CUR_ACC_LOOP_\n"); if(fun_type == NRN_CUR_SYN) P("_PRAGMA_FOR_CUR_SYN_ACC_LOOP_\n"); } P("for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n"); P("#else /* LAYOUT > 1 */ /*AoSoA*/\n"); P("#error AoSoA not implemented.\n"); P("for (;;) { /* help clang-format properly indent */\n"); P("#endif\n"); /* cache node index */ if (!artificial_cell) { P(" int _nd_idx = _ni[_iml];\n"); } } static void print_cuda_launcher_call(char *name) { P("\n#if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC)\n"); P(" NrnThread* d_nt = acc_deviceptr(_nt);\n"); P(" Memb_list* d_ml = acc_deviceptr(_ml);\n"); Fprintf(fcout, " nrn_%s_launcher(d_nt, d_ml, _type, _cntml_actual);\n", name); P(" return;\n"); P("#endif\n\n"); } void c_out_vectorize() { Item *q; extern int point_process; /* things which must go first and most declarations */ P("/* VECTORIZED */\n"); P("#include \n#include \n#include \n"); P("#undef PI\n"); printlist(defs_list); printlist(firstlist); if (modelline) { Fprintf(fcout, "static const char *modelname = \"%s\";\n\n", modelline); } else { Fprintf(fcout, "static const char *modelname = \"\";\n\n"); } Fflush(fcout); /* on certain internal errors partial output * is helpful */ P("static int error;\n"); P("static int _ninits = 0;\n"); P("static int _match_recurse=1;\n"); P("static void _modl_cleanup(){ _match_recurse=1;}\n"); funcdec(); Fflush(fcout); /* * translations of named blocks into functions, procedures, etc. Also * some special declarations used by some blocks */ printlist(procfunc); Fflush(fcout); /* Initialization function must always be present */ P("\nstatic inline void initmodel(_threadargsproto_) {\n int _i; double _save;"); P("{\n"); if (net_send_seen_ && !artificial_cell) { P(" Memb_list* _ml = _nt->_ml_list[_mechtype];\n"); } initstates(); printlist(initfunc); if (match_bound) { assert(!vectorize); P("\n_init_match(_save);"); } P("\n}\n}\n"); Fflush(fcout); /* generation of initmodel interface */ P("\nvoid nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("double* _p; Datum* _ppvar; ThreadDatum* _thread;\n"); P("double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual;\n"); P(" _ni = _ml->_nodeindices;\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("_thread = _ml->_thread;\n"); if (derivimplic_listnum) { sprintf(buf, " _deriv%d_advance = 0;\n" " #ifdef _OPENACC\n" " #pragma acc update device (_deriv%d_advance) if (_nt->compute_gpu)\n" " #endif\n" , derivimplic_listnum, derivimplic_listnum); P(buf); } if (net_send_seen_ && !artificial_cell) { P(" #pragma acc update device (_mechtype) if(_nt->compute_gpu)\n"); } ITERATE(q, newtonspace_list) { P(STR(q)); } /*check_tables();*/ /* @todo: will be done once anyway but it seems like this is bein copied * in many other places. See CNEUR-134 */ /* added data region in main fuction, need to verify that values are * correctly being used. * While testing with PGI compiler, we have seen incorrect spike if we * don't update celsius, not sure the reason. */ /* also PGI 16.3 (but not later) has the bizarre issue that celsius is 0 when an non file function, e.g. derivimplicit_thread, is called which calls back into the mod file. But the problem does not seem to impact other global variable defined in the mod file. With c++ files we declare routine seq in which case static variables can't be used. So, introducing _celsius_ as default implementation. */ P("_acc_globals_update();\n"); pr_layout_for_p(1, NRN_INIT); check_tables(); if (debugging_ && net_receive_) { P(" _tsav = -1e20;\n"); } if (!artificial_cell) {ext_vdef();} if (!artificial_cell) {P(" v = _v;\n _PRCELLSTATE_V\n");} printlist(get_ion_variables(1)); P(" initmodel(_threadargs_);\n"); printlist(set_ion_variables(2)); P("}\n"); P(" }\n"); /* end of the _nrn_skip_initmodel conditional */ if (derivimplic_listnum) { sprintf(buf, " _deriv%d_advance = 1;\n" " #ifdef _OPENACC\n" " #pragma acc update device (_deriv%d_advance) if (_nt->compute_gpu)\n" " #endif\n" , derivimplic_listnum, derivimplic_listnum); P(buf); } if (net_send_buffer_in_initial && !artificial_cell) { P("\ \n#if NET_RECEIVE_BUFFERING\ \n NetSendBuffer_t* _nsb = _ml->_net_send_buffer;\ \n#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\ \n #pragma acc wait(stream_id)\ \n #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu)\ \n update_net_send_buffer_on_host(_nt, _nsb);\ \n#endif\ \n {int _i;\ \n for (_i=0; _i < _nsb->_cnt; ++_i) {\ \n net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i],\ \n _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i],\ \n _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]);\ \n }}\ \n _nsb->_cnt = 0;\ \n#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\ \n #pragma acc update device(_nsb->_cnt) if(_nt->compute_gpu)\ \n#endif\ \n#endif\ \n"); } P("}\n"); /* standard modl EQUATION without solve computes current */ if (!conductance_) { P("\nstatic double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;"); #if CVODE if (cvode_nrn_current_solve_) { fprintf(fcout, "if (cvode_active_) { %s(_threadargs_); }\n", cvode_nrn_current_solve_->name); } #endif P("{"); if (currents->next != currents) { printlist(modelfunc); } ITERATE(q, currents) { Sprintf(buf, " _current += %s;\n", SYM(q)->name); P(buf); } P("\n} return _current;\n}\n"); } /* cuda interface */ P("\n#if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC)\n"); P(" void nrn_state_launcher(NrnThread*, Memb_list*, int, int);\n"); P(" void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int);\n"); P(" void nrn_cur_launcher(NrnThread*, Memb_list*, int, int);\n"); P("#endif\n\n"); /* For the classic BREAKPOINT block, the neuron current also has to compute the dcurrent/dv as well as make sure all currents accumulated properly (currents list) */ if (brkpnt_exists) { P("\nvoid nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); P("double* _p; Datum* _ppvar; ThreadDatum* _thread;\n"); P("int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual;\n"); P(" _ni = _ml->_nodeindices;\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("_thread = _ml->_thread;\n"); P("double * _vec_rhs = _nt->_actual_rhs;\n"); P("double * _vec_d = _nt->_actual_d;\n"); if (point_process) { P("double * _vec_shadow_rhs = _nt->_shadow_rhs;\n"); P("double * _vec_shadow_d = _nt->_shadow_d;\n"); } print_cuda_launcher_call("cur"); if(point_process) pr_layout_for_p(1, NRN_CUR_SYN); else pr_layout_for_p(1, NRN_CUR); ext_vdef(); if (currents->next != currents) { printlist(get_ion_variables(0)); #if CVODE cvode_rw_cur(buf); P(buf); } if (cvode_nrn_cur_solve_) { fprintf(fcout, "if (cvode_active_) { %s(_threadargs_); }\n", cvode_nrn_cur_solve_->name); } if (currents->next != currents) { #endif if (conductance_) { P(" {\n"); conductance_cout(); printlist(set_ion_variables(0)); P(" }\n"); }else{ P(" _g = _nrn_current(_threadargs_, _v + .001);\n"); printlist(begin_dion_stmt()); if (state_discon_list_) { P(" state_discon_flag_ = 1; _rhs = _nrn_current(_v); state_discon_flag_ = 0;\n"); }else{ P(" _rhs = _nrn_current(_threadargs_, _v);\n"); } printlist(end_dion_stmt(".001")); P(" _g = (_g - _rhs)/.001;\n"); /* set the ion variable values */ printlist(set_ion_variables(0)); } /* end of not conductance */ if (point_process) { P(" double _mfact = 1.e2/(_nd_area);\n"); P(" _g *= _mfact;\n"); P(" _rhs *= _mfact;\n"); } P(" _PRCELLSTATE_G\n"); if (electrode_current) { P("#if EXTRACELLULAR\n"); P(" if (_nd->_extnode) {\n"); P(" *_nd->_extnode->_rhs[0] += _rhs;\n"); P(" *_nd->_extnode->_d[0] += _g;\n"); P(" }\n"); P("#endif\n"); #if CACHEVEC == 0 P(" NODERHS(_nd) += _rhs;\n"); P(" NODED(_nd) -= _g;\n"); #else if (point_process) { rhs_d_pnt_race("+=", "-="); }else{ P(" _vec_rhs[_nd_idx] += _rhs;\n"); P(" _vec_d[_nd_idx] -= _g;\n"); P(print_fast_imem_code()); } #endif }else{ #if CACHEVEC == 0 P(" NODERHS(_nd) -= _rhs;\n"); P(" NODED(_nd) += _g;\n"); #else if (point_process) { rhs_d_pnt_race("-=", "+="); }else{ P(" _vec_rhs[_nd_idx] -= _rhs;\n"); P(" _vec_d[_nd_idx] += _g;\n"); } #endif } } P(" \n}\n"); P(" \n}\n"); if (0) { /* instead, jacobian handled in nrn_cur */ /* for the classic breakpoint block, nrn_cur computed the conductance, _g, and now the jacobian calculation merely returns that */ P("\nvoid nrn_jacob(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); P("double* _p; Datum* _ppvar; ThreadDatum* _thread;\n"); P("int* _ni; int _iml, _cntml_padded, _cntml_actual;\n"); P(" _ni = _ml->_nodeindices;\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("_thread = _ml->_thread;\n"); print_cuda_launcher_call("jacob"); pr_layout_for_p(0, NRN_JACOB); if (electrode_current) { #if CACHEVEC == 0 P(" NODED(_nd) -= _g;\n"); #else P(" VEC_D(_ni[_iml]) -= _g;\n"); #endif P("#if EXTRACELLULAR\n"); P(" if (_nd->_extnode) {\n"); P(" *_nd->_extnode->_d[0] += _g;\n"); P(" }\n"); P("#endif\n"); }else{ #if CACHEVEC == 0 P(" NODED(_nd) += _g;\n"); #else P(" VEC_D(_ni[_iml]) += _g;\n"); #endif } P(" \n}\n"); P(" \n}\n"); } } /*instead, jacobian handled in nrn_cur */ /* nrnstate list contains the EQUATION solve statement so this advances states by dt */ P("\nvoid nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); if (nrnstate || currents->next == currents) { P("double* _p; Datum* _ppvar; ThreadDatum* _thread;\n"); P("double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual;\n"); P(" _ni = _ml->_nodeindices;\n"); P("_cntml_actual = _ml->_nodecount;\n"); P("_cntml_padded = _ml->_nodecount_padded;\n"); P("_thread = _ml->_thread;\n"); print_cuda_launcher_call("state"); pr_layout_for_p(1, NRN_STATE); ext_vdef(); P(" v=_v;\n{\n"); printlist(get_ion_variables(1)); if (nrnstate) { printlist(nrnstate); } if (currents->next == currents) { printlist(modelfunc); } printlist(set_ion_variables(1)); P("}}\n"); } P("\n}\n"); P("\nstatic void terminal(){}\n"); /* vectorized: data must have own copies of slist and dlist for now we don't vectorize if slist or dlist exists. Eventually must separate initialization of static things from vectorized things. */ /* initlists() is called once to setup slist and dlist pointers */ P("\nstatic void _initlists(){\n"); P(" double _x; double* _p = &_x;\n"); P(" int _i; static int _first = 1;\n"); P(" int _cntml_actual=1;\n"); P(" int _cntml_padded=1;\n"); P(" int _iml=0;\n"); P(" if (!_first) return;\n"); printlist(initlist); P("_first = 0;\n}\n"); P("} // namespace coreneuron_lib\n"); } void vectorize_substitute(q, str) Item* q; char* str; { if (!vectorize_replacements) { vectorize_replacements = newlist(); } lappenditem(vectorize_replacements, q); lappendstr(vectorize_replacements, str); } Item* vectorize_replacement_item(Item* q) { Item* q1; if (vectorize_replacements) { ITERATE(q1, vectorize_replacements) { if (ITM(q1) == q) { return q1->next; } } } return (Item*)0; } void vectorize_do_substitute() { Item *q, *q1; if (vectorize_replacements) { ITERATE(q, vectorize_replacements) { q1 = ITM(q); q = q->next; replacstr(q1, STR(q)); } } } char* cray_pragma() { static char buf1[] = "\ \n#if _CRAY\ \n#pragma _CRI ivdep\ \n#endif\ \n"; return buf1; } #endif /*VECTORIZE*/ static void conductance_cout() { int i=0; Item* q; List* m; /* replace v with _v */ m = newlist(); ITERATE(q, modelfunc) { if (q->itemtype == SYMBOL) { if (strcmp(SYM(q)->name, "v") == 0) { lappendstr(m, "_v"); }else{ lappendsym(m, SYM(q)); } }else if (q->itemtype == STRING) { lappendstr(m, STR(q)); }else{ diag("modelfunc contains item which is not a SYMBOL or STRING", (char*)0); } } /* eliminate first { */ ITERATE(q, m) { if (q->itemtype == SYMBOL) { if (strcmp(SYM(q)->name, "{") == 0) { delete(q); break; } } } /* eliminate last } */ for (q = m->prev; q != m; q = q->prev) { if (q->itemtype == SYMBOL) { if (strcmp(SYM(q)->name, "}") == 0) { delete(q); break; } } } printlist(m); ITERATE(q, currents) { if (i == 0) { sprintf(buf, " _rhs = %s", breakpoint_current(SYM(q))->name); }else{ sprintf(buf, " + %s", breakpoint_current(SYM(q))->name); } P(buf); i += 1; } if (i > 0) { P(";\n"); } i = 0; ITERATE(q, conductance_) { if (i == 0) { sprintf(buf, " _g = %s", SYM(q)->name); }else{ sprintf(buf, " + %s", SYM(q)->name); } P(buf); i += 1; q = q->next; } if (i > 0) { P(";\n"); } ITERATE(q, conductance_) { if (SYM(q->next)) { sprintf(buf, " _ion_di%sdv += %s", SYM(q->next)->name, SYM(q)->name); P(buf); if (point_process) { P("* 1.e2/(_nd_area)"); } P(";\n"); } q = q->next; } } mod2c-8.2.2/src/mod2c_core/nocpout.c000066400000000000000000003054471425457616700172230ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/nocpout.c,v 4.1 1997/08/30 20:45:28 hines Exp */ /* nrnversion is a string that is passed via the _mechanism structure as the first arg. It will be interpreted within neuron to determine if that version is compatible with this version. For now try to use something of the form d.d If this is changed then also change nrnoc/init.c */ char* nmodl_version_ = "6.2.0"; /* Point processes are now interfaced to nrnoc via objectvars. Thus, p-array variables and functions accessible to hoc do not have suffixes, and there is a constructor, destructor. Also hoc interface functions always have a void* _vptr arg which is always cast to (Point_process*) and the _p and _ppvar pointers set. This makes the old setdata and create obsolete. */ /* The strategy is to use as much of parout and hparout method as possible. The bulk of the variables is in a p-array. The variables that don't belong in this p-array are indicated by a flag with sym->subtype & NRNNOTP. All other variables have values in that single array but not all those values are available from HOC. Variables accessible to NEURON are variables that appear within GLOBAL, SECTION, and RANGE statements. SECTION variables are not currently implemented. Variables that do not appear in the p-array are: 1)externally declared variables such as celsius, t. 2)parameters and assigned not declared in the NEURON{RANGE list} that are global with respect to sections. 3) variables static to this model, ie. v 4) read only variables like "diam" States always are in the p-array. USEION variables in the p-array have connections to other places and depending on the context may get their value from somewhere else, or add their value to somewhere else, or place their value somewhere else. The cases are: NONSPECIFIC and USEION WRITE i... value added to proper ion current and total current. USEION READ entry value assigned to local copy. USEION WRITE e.. ..o ..i exit value of local copy assigned to pointer.. It is an error for an ionic current or ionic variable to be a STATE. Use another variable as the state, make the ionic variable an ASSIGNED and just assign it at the proper place. Alternatively, if they are STATE's then they should not be READ since their value comes from the p-array itself. POINTER variables are like USEION variables. Unfortunately, it is up to the hoc user to make sure they point to the proper place with a connect statement. At this time we only check for a null pointer. The pointers are kept in the ppvar array. each model creates a setdata_suffix(x) (or setdata_suffix(i)) function which sets up _p and _ppvar for use by functions in the model called directly by hoc. */ /* FUNCTIONS are made external so they are callable from other models */ #define GLOBFUNCT 1 #include "modl.h" #include "parse1.h" #include #include #define GETWD(buf) getcwd(buf, NRN_BUFSIZE) #if VECTORIZE int vectorize = 1; /* the idea is to put all variables into a vector of vectors so there there is no static data. Every function has an implicit argument, underbar ix which tells which set of data _p[ix][...] to use. There are going to have to be limits on the kinds of scopmath functions called since many of them need static data. We can have special versions of the most useful of these. ie sparse.c. Above is obsolete in detail , underbar ix is no longer used. When vectorize = 1 then we believe the code is thread safe and most functions pass around _p, _ppvar, _thread. When vectorize is 0 then we are definitely not thread safe and _p and _ppvar are static. */ #endif #define NRNEXTRN 01 /* t, dt, celsius, etc. */ #define NRNCURIN 02 /* input value used */ #define NRNCUROUT 04 /* added to output value */ #define NRNRANGE 010 #define NRNPRANGEIN 020 #define NRNPRANGEOUT 040 #define NRNGLOBAL 0100 /* same for all sections, defined here */ #define NRNSTATIC 0200 /* v */ #define NRNNOTP 0400 /* doesn't belong in p array */ #define NRNIONFLAG 01000 /* temporary flag to allow READ and WRITE without declaring twice */ #define NRNSECTION 02000 #define NRNPOINTER 04000 #define IONCONC 010000 #define NRNBBCOREPOINTER 020000 #define IONEREV 0 /* Parameter */ #define IONIN 1 #define IONOUT 2 #define IONCUR 3 /* assigned */ #define IONDCUR 4 extern int assert_threadsafe; extern int brkpnt_exists; static char* brkpnt_str_; extern Symbol *indepsym; extern Symbol *scop_indep; extern List *indeplist; extern Symbol *stepsym; extern char *reprime(); extern List *symlist[]; extern List* ldifuslist; extern char* finname; extern int check_tables_threads(List*); List* acc_present_list; List *syminorder; List *plotlist; List *defs_list; List *units_def_for_acc; int electrode_current = 0; int thread_data_index = 0; List *thread_cleanup_list; List *thread_mem_init_list; List *newtonspace_list; List* toplocal_; extern int protect_; extern int protect_include_; extern List *set_ion_variables(), *get_ion_variables(); extern char* items_as_string(Item*, Item*); static int decode_limits(); static int decode_tolerance(); /* 1 means emit the relevant code since the model is a POINT_PROCESS with a NET_RECEIVE block and no net_send and so the NET_RECEIVE body can be executed on the GPU. _net_receive buffers the event for this type and thread and at the end of NetCvode::deliver_net_events, _net_buffer_receive is called so that the buffered events are delivered on the gpu all at once for this type and thread. In the c file, the define NET_RECEIVE_BUFFERING is used to conditionally compile the NET_RECEIVE block buffering code. */ int net_receive_buffering_; static void emit_net_receive_buffering_code(); static void emit_nrn_watch_check_code(); /* NEURON block information */ List *currents; List *useion; List* conductance_; List* breakpoint_local_current_; static List *rangeparm; static List *rangedep; static List *rangestate; static List *nrnpointers; static List* uip; /* void _update_ion_pointer(Datum* _ppvar){...} text */ char suffix[50]; extern char* modprefix; static char *rsuffix; /* point process range and functions don't have suffix*/ static char *mechname; static char* modbase; int point_process; /* 1 if a point process model */ int artificial_cell; /* 1 if also explicitly declared an ARTIFICIAL_CELL */ static int diamdec = 0; /*1 if diam is declared*/ static int areadec = 0; static int use_bbcorepointer = 0; static int use_celsius = 0; /* celsius is used */ static void defs_h(); static int iontype(); static void nrndeclare(); static void del_range(); static void declare_p(); static int iondef(); static void ion_promote(); static int ppvar_cnt; static List* ppvar_semantics_; static void ppvar_semantics(int, const char*); static int for_netcons_; /* number of FOR_NETCONS statements */ static Item* net_init_q1_; static Item* net_init_q2_; static int ba_index_; /* BEFORE AFTER blocks. See bablk */ static List* ba_list_; static List* acc_globals_update_list; #if CVODE List* state_discon_list_; static int cvode_emit, cvode_not_allowed, cvode_ieq_index; static int cond_index; static int tqitem_index; static int watch_index; static int cvode_index; static List* ion_synonym; extern int singlechan_; int debugging_; int net_receive_; int net_send_seen_; int net_event_seen_; int watch_seen_; /* number of WATCH statements + 1*/ List* watch_data_; /* triples of par1, par2, flag */ static Item* net_send_delivered_; /* location for if flag is 1 then clear the tqitem_ to allow an error message for net_move */ static Item* net_receive_block_begin_; /* the "void _net_receive" line */ static Item* net_receive_block_open_brace_; /* the "{" line */ #endif #define SYMITER(arg) ITERATE(q, syminorder){ \ s = SYM(q); if (s->type == arg) #define SYMLISTITER for (i = 'A'; i <= 'z'; i++)\ ITERATE(q, symlist[i]) #define IFTYPE(arg) if ((s->subtype & arg)\ && ( (s->usage & EXPLICIT_DECL) != automatic) ) /* varcount holds the index into the .var file and is saved in s->used parraycount holds the index into the p array and is saved in s->varnum pvarcount indexes pointers to variables such as ena */ static int varcount, parraycount; void set_suffix() { for (modbase = modprefix + strlen(modprefix); modbase != modprefix; modbase--) { if (*modbase == '\\' || *modbase == '/') { modbase++; break; } } if (!mechname) { sprintf(suffix,"_%s", modbase); mechname = modbase; } else if (strcmp(mechname, "nothing") == 0) { vectorize = 0; suffix[0] = '\0'; mechname = modbase; }else{ sprintf(suffix, "_%s", mechname); } } void nrninit() { extern int using_default_indep; currents = newlist(); rangeparm = newlist(); rangedep = newlist(); rangestate = newlist(); useion = newlist(); nrnpointers = newlist(); using_default_indep = 0; indepinstall(install("t", NAME), "0", "1", "100", (Item*)0, "ms", 0); using_default_indep = 1; debugging_ = 1; thread_cleanup_list = newlist(); thread_mem_init_list = newlist(); newtonspace_list = newlist(); } void parout() { int i, j, ioncount, pointercount, gind, emit_check_table_thread; Item *q, *q1, *extra_pragma_loop_arg; Symbol *s, *sion; double d1, d2; #if BBCORE cvode_emit = 0; #endif defs_list = newlist(); /* relates hoc names to c-variables */ if (brkpnt_exists) { if (vectorize) { brkpnt_str_ = "nrn_cur, NULL, nrn_state"; }else{ brkpnt_str_ = "nrn_cur, nrn_jacob, nrn_state"; } }else{ brkpnt_str_ = "0, 0, 0"; #if 1 || defined(__MINGW32__) /* x86_64-w64-mingw32-gcc passed 0 without zeroing the high 32 bits */ /* also cygwin64 gcc 4.8.1, so cast to void* universally */ brkpnt_str_ = "NULL, NULL, NULL"; #endif } set_suffix(); if (artificial_cell && vectorize && (thread_data_index || toplocal_)) { fprintf(stderr, "Notice: ARTIFICIAL_CELL models that would require thread specific data are not thread safe.\n"); vectorize = 0; } if (point_process) { rsuffix = ""; }else{ rsuffix = suffix; } if (point_process && !artificial_cell && net_receive_) { net_receive_buffering_ = 1; emit_net_receive_buffering_code(); } Lappendstr(defs_list, "\ \n#include \"coreneuron/utils/randoms/nrnran123.h\"\ \n#include \"coreneuron/nrnoc/md1redef.h\"\ \n#include \"coreneuron/nrnconf.h\"\ \n#include \"coreneuron/sim/multicore.hpp\"\ \n#include \"coreneuron/nrniv/nrniv_decl.h\"\ \n#include \"coreneuron/utils/ivocvect.hpp\"\ \n#include \"coreneuron/utils/nrnoc_aux.hpp\"\ \n#include \"coreneuron/gpu/nrn_acc_manager.hpp\"\ \n#include \"coreneuron/sim/scopmath/newton_struct.h\"\ \n#include \"coreneuron/sim/scopmath/newton_thread.hpp\"\ \n#include \"coreneuron/sim/scopmath/sparse_thread.hpp\"\ \n#include \"coreneuron/sim/scopmath/ssimplic_thread.hpp\"\ \n#include \"coreneuron/nrnoc/md2redef.h\"\ \n#include \"coreneuron/mechanism/register_mech.hpp\"\ \n#if !NRNGPU\ \n#if !defined(DISABLE_HOC_EXP)\ \n#undef exp\ \n#define exp hoc_Exp\ \n#endif\ \n#endif\n\ "); if (protect_include_) { Lappendstr(defs_list, "\n#include \"nmodlmutex.h\""); } if (use_bbcorepointer) { Lappendstr(defs_list, "#define _threadargsproto_namespace int _iml, int _cntml_padded, double* _p, coreneuron::Datum* _ppvar, coreneuron::ThreadDatum* _thread, coreneuron::NrnThread* _nt, double v\n"); lappendstr(defs_list, "static void bbcore_read(double *, int*, int*, int*, _threadargsproto_namespace);\n"); lappendstr(defs_list, "static void bbcore_write(double *, int*, int*, int*, _threadargsproto_namespace);\n"); } Lappendstr(defs_list, "namespace coreneuron {\n"); if (vectorize) { /* macros for compiler dependent ivdep like pragma and memory layout. INIT and STATE pragma are same * except that sync clause absent because we saw issue only in CaDynamics_E2 */ extra_pragma_loop_arg = lappendstr(defs_list, "\ \n#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\ \n#include \ \n#define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma(\"acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)\")\ \n#define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma(\"acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)\")\ \n#define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma(\"acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)\")\ \n#define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma(\"acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)\")\ \n#define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma(\"acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)\")\ \n#else\ \n#define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma(\"\")\ \n#define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma(\"\")\ \n#define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma(\"\")\ \n#define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma(\"\")\ \n#define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma(\"\")\ \n#endif\ \n \ \n#if defined(__ICC) || defined(__INTEL_COMPILER)\ \n#define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma(\"ivdep\")\ \n#elif defined(__IBMC__) || defined(__IBMCPP__)\ \n#define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma(\"ibm independent_loop\")\ \n#elif defined(__PGI)\ \n#define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma(\"vector\")\ \n#elif defined(_CRAYC)\ \n#define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma(\"_CRI ivdep\")\ \n#elif defined(__clang__)\ \n#define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma(\"clang loop vectorize(enable)\")\ \n#elif defined(__GNUC__) || defined(__GNUG__)\ \n#define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma(\"GCC ivdep\")\ \n#else\ \n#define _PRAGMA_FOR_VECTOR_LOOP_\ \n#endif // _PRAGMA_FOR_VECTOR_LOOP_\ \n \ \n#if !defined(LAYOUT)\ \n/* 1 means AoS, >1 means AoSoA, <= 0 means SOA */\ \n#define LAYOUT 1\ \n#endif\ \n#if LAYOUT >= 1\ \n#define _STRIDE LAYOUT\ \n#else\ \n#define _STRIDE _cntml_padded + _iml\ \n#endif\ \n"); }else{ Lappendstr(defs_list, "\ \n#undef LAYOUT\ \n#define LAYOUT 1\ \n#define _STRIDE 1\ \n"); } if (net_receive_buffering_) { Lappendstr(defs_list, "\ \n\ \n#if !defined(NET_RECEIVE_BUFFERING)\ \n#define NET_RECEIVE_BUFFERING 1\ \n#endif\ \n"); } #if 1 /* for easier profiling, give distinct names to otherwise reused static names */ sprintf(buf, "\n\ #define nrn_init _nrn_init_%s\n\ #define nrn_cur _nrn_cur_%s\n\ #define _nrn_current _nrn_current_%s\n\ #define nrn_jacob _nrn_jacob_%s\n\ #define nrn_state _nrn_state_%s\n\ #define initmodel initmodel_%s\n\ #define _net_receive _net_receive_%s\n\ #define _net_init _net_init_%s\n\ #define nrn_state_launcher nrn_state%s_launcher\n\ #define nrn_cur_launcher nrn_cur%s_launcher\n\ #define nrn_jacob_launcher nrn_jacob%s_launcher\ ", suffix, suffix, suffix, suffix, suffix, suffix, suffix, suffix, suffix, suffix, suffix); Lappendstr(defs_list, buf); if (net_receive_buffering_) { sprintf(buf, "\ \n#if NET_RECEIVE_BUFFERING\ \n#define _net_buf_receive _net_buf_receive%s\ \nvoid _net_buf_receive(NrnThread*);\ \n#endif\ \n", suffix); Lappendstr(defs_list, buf); } if (watch_seen_) { sprintf(buf, "\n#define _nrn_watch_check _nrn_watch_check_%s", suffix); Lappendstr(defs_list, buf); } SYMLISTITER { Symbol* s = SYM(q); /* note that with GLOBFUNCT, FUNCT will be redefined anyway */ if (s->type == NAME && s->subtype & (PROCED | DERF | KINF)) { sprintf(buf, "\n#define %s %s%s", s->name, s->name, suffix); Lappendstr(defs_list, buf); } } Lappendstr(defs_list, "\n"); #endif /* distinct names for easier profiling */ Lappendstr(defs_list, "\n\ #undef _threadargscomma_\n\ #undef _threadargsprotocomma_\n\ #undef _threadargs_\n\ #undef _threadargsproto_\n\ "); if (vectorize) { Lappendstr(defs_list, "\n\ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v,\n\ #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v,\n\ #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v\n\ #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v\n\ "); }else{ Lappendstr(defs_list, "\n\ #define _threadargscomma_ /**/\n\ #define _threadargsprotocomma_ /**/\n\ #define _threadargs_ /**/\n\ #define _threadargsproto_ /**/\n\ "); } Lappendstr(defs_list, "\ /*SUPPRESS 761*/\n\ /*SUPPRESS 762*/\n\ /*SUPPRESS 763*/\n\ /*SUPPRESS 765*/\n\ "); #if VECTORIZE if (vectorize) { Sprintf(buf, "/* Thread safe. No static _p or _ppvar. */\n"); }else #endif { Sprintf(buf, "static double *_p; static Datum *_ppvar;\n"); } Lappendstr(defs_list, buf); nrndeclare(); varcount = parraycount = 0; declare_p(); ioncount = iondef(&pointercount); /* first is _nd_area if point process */ Lappendstr(defs_list, "\n#if MAC\n#if !defined(v)\n#define v _mlhv\n#endif\n#if !defined(h)\n#define h _mlhh\n#endif\n#endif\n"); Lappendstr(defs_list, "static int hoc_nrnpointerindex = "); if (pointercount) { q = nrnpointers->next; Sprintf(buf, "%d;\n", SYM(q)->used); }else{ Sprintf(buf, "-1;\n"); } Lappendstr(defs_list, buf); /*above modified to also count and define pointers*/ if (vectorize) { Lappendstr(defs_list, "static ThreadDatum* _extcall_thread;\n"); } #if 0 Lappendstr(defs_list, "/* static variables special to NEURON */\n"); SYMLISTITER { if (SYM(q)->nrntype & NRNSTATIC) { Sprintf(buf, "static double %s;\n", SYM(q)->name); Lappendstr(defs_list, buf); } } #endif ITERATE(q, units_def_for_acc) { Sprintf(buf, "#define %s %s%s\n", STR(q), STR(q), suffix); Lappendstr(defs_list, buf); } Lappendstr(defs_list, "/* external NEURON variables */\n"); SYMLISTITER { s = SYM(q); if (s->nrntype & NRNEXTRN) { if (strcmp(s->name, "dt") == 0) { continue; } if (strcmp(s->name, "t") == 0) { continue; } if (s->subtype & ARRAY) { Sprintf(buf, "extern double* %s;\n", s->name); }else{ Sprintf(buf, "extern double %s;\n", s->name); } Lappendstr(defs_list, buf); if (strcmp(s->name, "celsius") == 0) { use_celsius = 1; Sprintf(buf, "#define _celsius_ _celsius_%s\n" "double _celsius_;\n" "#pragma acc declare copyin(_celsius_)\n", suffix); Lappendstr(defs_list, buf); } } } #if BBCORE Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif Lappendstr(defs_list, "/* declaration of user functions */\n"); SYMLISTITER { s = SYM(q); if (s->subtype & (FUNCT | PROCED) && s->name[0] != '_') { if (point_process) { Sprintf(buf, "static double _hoc_%s();\n", s->name); }else{ Sprintf(buf, "static void _hoc_%s(void);\n", s->name); } Lappendstr(defs_list, buf); } } #if BBCORE Lappendstr(defs_list, "\n#endif /*BBCORE*/\n"); #endif q = lappendstr(defs_list, "static int _mechtype;\n"); if (net_send_seen_ && !artificial_cell) { Sprintf(buf, "\n#define _mechtype _mechtype%s\n" "int _mechtype;\n" "#pragma acc declare copyin (_mechtype)\n" , suffix); replacstr(q, buf); } /**** create special point process functions */ if (point_process) { Lappendstr(defs_list, "static int _pointtype;\n"); #if BBCORE Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif Lappendstr(defs_list, "static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process();\n"); Lappendstr(defs_list, "return create_point_process(_pointtype, _ho);\n}\n"); Lappendstr(defs_list, "static void _hoc_destroy_pnt();\n"); Lappendstr(defs_list, "static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process();\n"); Lappendstr(defs_list, "return loc_point_process(_pointtype, _vptr);\n}\n"); Lappendstr(defs_list, "static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point();\n"); Lappendstr(defs_list, "return has_loc_point(_vptr);\n}\n"); Lappendstr(defs_list, "static double _hoc_get_loc_pnt(_vptr)void* _vptr; {\n"); Lappendstr(defs_list, "double get_loc_point_process(); return (get_loc_point_process(_vptr));\n}\n"); #if BBCORE Lappendstr(defs_list, "\n#endif /*BBCORE*/\n"); #endif } /* functions */ #if BBCORE Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif Lappendstr(defs_list, "/* connect user functions to hoc names */\n"); Lappendstr(defs_list,"static VoidFunc hoc_intfunc[] = {\n"); if (point_process) { Lappendstr(defs_list,"0,0\n};\n"); Lappendstr(defs_list, "static Member_func _member_func[] = {\n"); Sprintf(buf, "\"loc\", _hoc_loc_pnt,\n"); Lappendstr(defs_list, buf); Sprintf(buf, "\"has_loc\", _hoc_has_loc,\n"); Lappendstr(defs_list, buf); Sprintf(buf, "\"get_loc\", _hoc_get_loc_pnt,\n"); Lappendstr(defs_list, buf); }else{ Sprintf(buf, "\"setdata_%s\", _hoc_setdata,\n", mechname); Lappendstr(defs_list, buf); } SYMLISTITER { s = SYM(q); if ((s->subtype & (FUNCT | PROCED)) && s->name[0] != '_') { Sprintf(buf, "\"%s%s\", _hoc_%s,\n", s->name, rsuffix, s->name); Lappendstr(defs_list, buf); } } Lappendstr(defs_list, "0, 0\n};\n"); #if BBCORE Lappendstr(defs_list, "\n#endif /*BBCORE*/\n"); #endif #if GLOBFUNCT /* FUNCTION's are now global so callable from other models */ /* change name to namesuffix. This propagates everywhere except to hoc_name*/ /* but don't do it if suffix is empty */ if (suffix[0]) SYMLISTITER { s = SYM(q); if ((s->subtype & FUNCT)) { Sprintf(buf, "#define %s %s%s\n", s->name, s->name, suffix); q1 = Lappendstr(defs_list, buf); q1->itemtype = VERBATIM; } } SYMLISTITER { int j; s = SYM(q); if ((s->subtype & FUNCT)) { if(!artificial_cell) { Lappendstr(defs_list, "#pragma acc routine seq\n"); } Sprintf(buf, "inline double %s(", s->name); Lappendstr(defs_list, buf); if (vectorize && !s->no_threadargs) { if (s->varnum) { Lappendstr(defs_list, "_threadargsprotocomma_"); }else{ Lappendstr(defs_list, "_threadargsproto_"); } } for (j=0; j < s->varnum; ++j) { Lappendstr(defs_list, "double"); if (j+1 < s->varnum) { Lappendstr(defs_list, ","); } } Lappendstr(defs_list, ");\n"); } } #endif emit_check_table_thread = 0; if (vectorize && check_tables_threads(defs_list)) { emit_check_table_thread = 1; } /* per thread top LOCAL */ /* except those that are marked assigned_to_ == 2 stay static double */ if (vectorize && toplocal_) { int cnt; cnt = 0; ITERATE(q, toplocal_) { if (SYM(q)->assigned_to_ != 2) { if (SYM(q)->subtype & ARRAY) { cnt += SYM(q)->araydim; }else{ ++cnt; } } } sprintf(buf, " _thread[%d]._pval = (double*)ecalloc(%d, sizeof(double));\n", thread_data_index, cnt); lappendstr(thread_mem_init_list, buf); sprintf(buf, " free((void*)(_thread[%d]._pval));\n", thread_data_index); lappendstr(thread_cleanup_list, buf); cnt = 0; ITERATE(q, toplocal_) { if (SYM(q)->assigned_to_ != 2) { if (SYM(q)->subtype & ARRAY) { sprintf(buf, "#define %s (_thread[%d]._pval + %d)\n", SYM(q)->name, thread_data_index, cnt); cnt += SYM(q)->araydim; }else{ sprintf(buf, "#define %s _thread[%d]._pval[%d]\n", SYM(q)->name, thread_data_index, cnt); ++cnt; } }else{ /* stay file static */ if (SYM(q)->subtype & ARRAY) { sprintf(buf, "static double %s[%d];\n", SYM(q)->name, SYM(q)->araydim); }else{ sprintf(buf, "static double %s;\n", SYM(q)->name); } } lappendstr(defs_list, buf); } ++thread_data_index; } /* per thread global data */ gind = 0; if (vectorize) SYMLISTITER { s = SYM(q); if (s->nrntype & (NRNGLOBAL) && s->assigned_to_ == 1) { if (s->subtype & ARRAY) { gind += s->araydim; }else{ ++gind; } } } /* double scalars declared internally */ Lappendstr(defs_list, "/* declare global and static user variables */\n"); if (gind) { sprintf(buf, "static int _thread1data_inuse = 0;\nstatic double _thread1data[%d];\n#define _gth %d\n", gind, thread_data_index); Lappendstr(defs_list, buf); sprintf(buf, " if (_thread1data_inuse) {_thread[_gth]._pval = (double*)ecalloc(%d, sizeof(double));\n }else{\n _thread[_gth]._pval = _thread1data; _thread1data_inuse = 1;\n }\n", gind); lappendstr(thread_mem_init_list, buf); lappendstr(thread_cleanup_list, " if (_thread[_gth]._pval == _thread1data) {\n _thread1data_inuse = 0;\n }else{\n free((void*)_thread[_gth]._pval);\n }\n"); ++thread_data_index; } gind = 0; acc_globals_update_list = newlist(); SYMLISTITER { /* globals are now global with respect to C as well as hoc */ s = SYM(q); if (s->nrntype & (NRNGLOBAL)) { if (vectorize && s->assigned_to_ == 1) { if (s->subtype & ARRAY) { sprintf(buf, "#define %s%s (_thread1data + %d)\n\ #define %s (_thread[_gth]._pval + %d)\n", s->name, suffix, gind, s->name, gind); }else{ sprintf(buf, "#define %s%s _thread1data[%d]\n\ #define %s _thread[_gth]._pval[%d]\n", s->name, suffix, gind, s->name, gind); } q1 = Lappendstr(defs_list, buf); q1->itemtype = VERBATIM; if (s->subtype & ARRAY) { gind += s->araydim; }else{ ++gind; } continue; } if (suffix[0]) { Sprintf(buf, "#define %s %s%s\n", s->name, s->name, suffix); q1 = Lappendstr(defs_list, buf); q1->itemtype = VERBATIM; } decode_ustr(s, &d1, &d2, buf); if (s->subtype & ARRAY) { Sprintf(buf, "double %s[%d];\n", s->name, s->araydim); }else{ Sprintf(buf, "double %s = %g;\n", s->name, d1); } Lappendstr(defs_list, buf); #if BBCORE if (s->subtype & ARRAY) { Sprintf(buf, "#pragma acc declare copyin (%s,%d)\n", s->name, s->araydim); }else{ Sprintf(buf, "#pragma acc declare copyin (%s)\n", s->name); } Lappendstr(defs_list, buf); if (s->subtype & ARRAY) { Sprintf(buf, "#pragma acc update device (%s,%d) if(nrn_threads->compute_gpu)\n", s->name, s->araydim); }else{ Sprintf(buf, "#pragma acc update device (%s) if(nrn_threads->compute_gpu)\n", s->name); } Lappendstr(acc_globals_update_list, buf); #endif } } #if BBCORE if (acc_globals_update_list) { Lappendstr(defs_list, "\nstatic void _acc_globals_update() {\n"); if (acc_globals_update_list->next != acc_globals_update_list) { movelist(acc_globals_update_list->next, acc_globals_update_list->prev, defs_list); } if (use_celsius) { Lappendstr(defs_list, "_celsius_ = celsius;\n"); Lappendstr(defs_list, "#pragma acc update device(_celsius_)\n"); } Lappendstr(defs_list, "}\n\n"); } if (use_celsius) { Lappendstr(defs_list, "#define celsius _celsius_\n"); } Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif Lappendstr(defs_list, "/* some parameters have upper and lower limits */\n"); Lappendstr(defs_list, "static HocParmLimits _hoc_parm_limits[] = {\n"); SYMLISTITER { s = SYM(q); if (s->subtype & PARM) { double d1=0., d2=0.; if (decode_limits(s, &d1, &d2)) { if (s->nrntype & NRNGLOBAL || !point_process) { Sprintf(buf, "\"%s%s\", %g, %g,\n", s->name, suffix, d1, d2); }else{ Sprintf(buf, "\"%s\", %g, %g,\n", s->name, d1, d2); } Lappendstr(defs_list, buf); } } } Lappendstr(defs_list, "0,0,0\n};\n"); units_reg(); #if BBCORE Lappendstr(defs_list, "\n#endif /*BBCORE*/\n"); #endif SYMLISTITER { s = SYM(q); if (s->nrntype & (NRNSTATIC)) { #if VECTORIZE && 0 if (vectorize) { diag("No statics allowed for thread safe models:", s->name); } #endif decode_ustr(s, &d1, &d2, buf); if (s->subtype & ARRAY) { Sprintf(buf, "static double %s[%d];\n" "#pragma acc declare create(%s)\n", s->name, s->araydim, s->name); }else{ Sprintf(buf, "static double %s = %g;\n" "#pragma acc declare copyin(%s)\n", s->name, d1, s->name); } Lappendstr(defs_list, buf); } } Lappendstr(defs_list, "/* connect global user variables to hoc */\n"); Lappendstr(defs_list,"static DoubScal hoc_scdoub[] = {\n"); ITERATE(q, syminorder) { s = SYM(q); if (s->nrntype & NRNGLOBAL && !(s->subtype & ARRAY)) { Sprintf(buf, "\"%s%s\", &%s%s,\n", s->name, suffix, s->name, suffix); Lappendstr(defs_list, buf); } } Lappendstr(defs_list, "0,0\n};\n"); /* double vectors */ Lappendstr(defs_list,"static DoubVec hoc_vdoub[] = {\n"); ITERATE(q, syminorder) { s = SYM(q); if (s->nrntype & NRNGLOBAL && (s->subtype & ARRAY)) { Sprintf(buf, "\"%s%s\", %s%s, %d,\n", s->name, suffix, s->name, suffix, s->araydim); Lappendstr(defs_list, buf); } } Lappendstr(defs_list, "0,0,0\n};\n"); Lappendstr(defs_list, "static double _sav_indep;\n"); if (ba_index_ > 0) { Lappendstr(defs_list, "static void _ba1(NrnThread*, Memb_list*, int)"); for (i=2; i <= ba_index_; ++i) { sprintf(buf, ", _ba%d(NrnThread*, Memb_list*, int)", i); Lappendstr(defs_list, buf); } Lappendstr(defs_list, ";\n"); } /******** what normally goes into cabvars.h structures */ /*declaration of the range variables names to HOC */ Lappendstr(defs_list, "static void nrn_alloc(double*, Datum*, int);\nvoid nrn_init(NrnThread*, Memb_list*, int);\nvoid nrn_state(NrnThread*, Memb_list*, int);\n\ "); if (brkpnt_exists) { Lappendstr(defs_list, "void nrn_cur(NrnThread*, Memb_list*, int);\n"); if (!vectorize) { Lappendstr(defs_list, "void nrn_jacob(NrnThread*, Memb_list*, int);\n"); } } if (watch_seen_) { Lappendstr(defs_list, "void _nrn_watch_check(NrnThread*, Memb_list*);\n"); } /* count the number of pointers needed */ ppvar_cnt = ioncount + diamdec + pointercount + areadec; #if CVODE if (net_send_seen_) { tqitem_index = ppvar_cnt; ppvar_semantics(ppvar_cnt, "netsend"); ppvar_cnt++; } if (watch_seen_) { watch_index = ppvar_cnt; for (i=0; i < watch_seen_ ; ++i) { ppvar_semantics(i+ppvar_cnt, "watch"); } ppvar_cnt += watch_seen_; sprintf(buf, "\n#define _watch_array(arg) _ppvar[(arg + %d)*_STRIDE]", watch_index); Lappendstr(defs_list, buf); Lappendstr(defs_list, "\n"); sprintf(buf, "\n" "#define _nrn_watch_activate(_item)\\\n" " if (_watch_rm == 0) {\\\n" " int _i;\\\n" " for (_i = 1; _i < %d; ++_i) {\\\n" " _watch_array(_i) = 0;\\\n" " }\\\n" " _watch_rm = 1;\\\n" " }\\\n" " _watch_array(_item) = 2 +" , watch_seen_); Lappendstr(defs_list, buf); } if (for_netcons_) { sprintf(buf, "\n#define _fnc_index %d\n", ppvar_cnt); Lappendstr(defs_list, buf); ppvar_semantics(ppvar_cnt, "fornetcon"); ppvar_cnt += 1; } if (point_process) { #if BBCORE Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif Lappendstr(defs_list, "static void _hoc_destroy_pnt(_vptr) void* _vptr; {\n"); if (watch_seen_ || for_netcons_) { Lappendstr(defs_list, " Prop* _prop = ((Point_process*)_vptr)->_prop;\n"); } #if 0 if (watch_seen_) { sprintf(buf, " if (_prop) { _nrn_free_watch(_prop->dparam, %d, %d);}\n", watch_index, watch_seen_); Lappendstr(defs_list, buf); } #endif if (for_netcons_) { sprintf(buf, " if (_prop) { _nrn_free_fornetcon(&(_prop->dparam[_fnc_index]._pvoid));}\n"); Lappendstr(defs_list, buf); } Lappendstr(defs_list, " destroy_point_process(_vptr);\n}\n"); #if BBCORE Lappendstr(defs_list, "\n#endif /*BBCORE*/\n"); #endif } if (cvode_emit) { cvode_ieq_index = ppvar_cnt; ppvar_semantics(ppvar_cnt, "cvodeieq"); ppvar_cnt++; } cvode_emit_interface(); #endif if (destructorfunc->next != destructorfunc) { if (! point_process) { diag("DESTRUCTOR only permitted for POINT_PROCESS", (char*)0); } Lappendstr(defs_list, "\n" "#if 0 /*BBCORE*/\n" "static void _destructor(Prop*);\n" "#endif\n" ); } if (constructorfunc->next != constructorfunc) { Lappendstr(defs_list, "\n" "#if 0 /*BBCORE*/\n" "static void _constructor(Prop*);\n" "#endif\n" ); } Lappendstr(defs_list, "/* connect range variables in _p that hoc is supposed to know about */\n"); Lappendstr(defs_list, "\ static const char *_mechanism[] = {\n\ "); Sprintf(buf, "\"%s\",\n\"%s\",\n", nmodl_version_, mechname); Lappendstr(defs_list, buf); ITERATE(q, rangeparm) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "\"%s%s[%d]\",\n", s->name, rsuffix, s->araydim); }else{ Sprintf(buf, "\"%s%s\",\n", s->name, rsuffix); } Lappendstr(defs_list, buf); } Lappendstr(defs_list, "0,\n"); ITERATE(q, rangedep) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "\"%s%s[%d]\",\n", s->name, rsuffix, s->araydim); }else{ Sprintf(buf, "\"%s%s\",\n", s->name, rsuffix); } Lappendstr(defs_list, buf); } Lappendstr(defs_list, "0,\n"); ITERATE(q, rangestate) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "\"%s%s[%d]\",\n", s->name, rsuffix, s->araydim); }else{ Sprintf(buf, "\"%s%s\",\n", s->name, rsuffix); } Lappendstr(defs_list, buf); } Lappendstr(defs_list, "0,\n"); /* pointer variable names */ ITERATE(q, nrnpointers) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "\"%s%s[%d]\",\n", s->name, rsuffix, s->araydim); }else{ Sprintf(buf, "\"%s%s\",\n", s->name, rsuffix); } Lappendstr(defs_list, buf); } Lappendstr(defs_list, "0};\n"); /*********Creation of the allocation function*/ if (diamdec) { Lappendstr(defs_list, "static Symbol* _morphology_sym;\n"); } #if !BBCORE if (areadec) { Lappendstr(defs_list, "extern Node* nrn_alloc_node_;\n"); } #endif ITERATE(q, useion) { sion = SYM(q); Sprintf(buf, "static int _%s_type;\n",sion->name); Lappendstr(defs_list, buf); if (ldifuslist) { sprintf(buf, "static int _type_i%s;\n", sion->name); lappendstr(defs_list, buf); } q=q->next->next->next; } Lappendstr(defs_list, "\n\ static void nrn_alloc(double* _p, Datum* _ppvar, int _type) {\n"); #if BBCORE Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif Lappendstr(defs_list, " /*initialize range parameters*/\n"); ITERATE(q, rangeparm) { s = SYM(q); if (s->subtype & ARRAY) { continue; } decode_ustr(s, &d1, &d2, buf); Sprintf(buf, " %s = %g;\n", s->name, d1); Lappendstr(defs_list, buf); } if (diamdec) { ppvar_semantics(ioncount + pointercount, "diam"); } if (areadec) { ppvar_semantics(ioncount + pointercount + diamdec, "area"); } if (point_process) { ioncount = 2; }else{ ioncount = 0; } ITERATE(q, useion) { int dcurdef = 0; int need_style = 0; sion = SYM(q); Sprintf(buf, "prop_ion = need_memb(_%s_sym);\n", sion->name); Lappendstr(defs_list, buf); if (ldifuslist) { sprintf(buf, " _type_i%s = prop_ion->_type;\n", sion->name); lappendstr(defs_list, buf); } ion_promote(q); q=q->next; ITERATE(q1, LST(q)) { SYM(q1)->nrntype |= NRNIONFLAG; Sprintf(buf, "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* %s */\n", ioncount++, iontype(SYM(q1)->name, sion->name), SYM(q1)->name); Lappendstr(defs_list, buf); } q=q->next; ITERATE(q1, LST(q)) { int itype = iontype(SYM(q1)->name, sion->name); if (SYM(q1)->nrntype & NRNIONFLAG) { SYM(q1)->nrntype &= ~NRNIONFLAG; }else{ Sprintf(buf, "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* %s */\n", ioncount++, itype, SYM(q1)->name); Lappendstr(defs_list, buf); } if (itype == IONCUR) { dcurdef = 1; Sprintf(buf, "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* _ion_di%sdv */\n", ioncount++, IONDCUR, sion->name); Lappendstr(defs_list, buf); } if (itype == IONIN || itype == IONOUT) { need_style = 1; } } if (need_style) { Sprintf(buf, "\t_ppvar[%d]._pvoid = (void*)(&(prop_ion->dparam[0]._i)); /* iontype for %s */\n", ioncount++, sion->name); Lappendstr(defs_list, buf); } q=q->next; if (!dcurdef && ldifuslist) { Sprintf(buf, "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* _ion_di%sdv */\n", ioncount++, IONDCUR, sion->name); Lappendstr(defs_list, buf); } } #if BBCORE Lappendstr(defs_list, "\n#endif /* BBCORE */\n"); #endif if (constructorfunc->next != constructorfunc) { Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n" "if (!nrn_point_prop_) {_constructor(_prop);}\n" "#endif\n" ); if (vectorize) { Lappendstr(procfunc, "\n\ #if 0 /*BBCORE*/\n\ static _constructor(_prop)\n\ Prop *_prop; double* _p; Datum* _ppvar; ThreadDatum* _thread;\n\ {\n\ _thread = (Datum*)0;\n\ _p = _prop->param; _ppvar = _prop->dparam;\n\ {\n\ "); }else{ Lappendstr(procfunc, "\n\ #if 0 /*BBCORE*/\n\ static void _constructor(Prop* _prop) {\n\ _p = _prop->param; _ppvar = _prop->dparam;\n\ {\n\ "); } movelist(constructorfunc->next, constructorfunc->prev, procfunc); Lappendstr(procfunc, "\n}\n}\n#endif /*BBCORE*/\n"); } Lappendstr(defs_list, "\n}\n"); Lappendstr(defs_list, "static void _initlists();\n"); #if CVODE if (cvode_emit) { Lappendstr(defs_list, " /* some states have an absolute tolerance */\n"); Lappendstr(defs_list, "static Symbol** _atollist;\n"); Lappendstr(defs_list, "static HocStateTolerance _hoc_state_tol[] = {\n"); ITERATE(q, rangestate) { double d1; s = SYM(q); if (decode_tolerance(s, &d1)) { if (!point_process) { Sprintf(buf, "\"%s%s\", %g,\n", s->name, suffix, d1); }else{ Sprintf(buf, "\"%s\", %g,\n", s->name, d1); } Lappendstr(defs_list, buf); } } Lappendstr(defs_list, "0,0\n};\n"); } if (singlechan_) { sprintf(buf, "static _singlechan_declare%d();\n", singlechan_); Lappendstr(defs_list, buf); } #endif #if VECTORIZE if (net_send_seen_) { if (!net_receive_) { diag("can't use net_send if there is no NET_RECEIVE block", (char*)0); } sprintf(buf, "\n#define _tqitem &(_nt->_vdata[_ppvar[%d*_STRIDE]])\n", tqitem_index); Lappendstr(defs_list, buf); if (net_receive_buffering_) { sprintf(buf, "\ \n#if NET_RECEIVE_BUFFERING\ \n#undef _tqitem\ \n#define _tqitem _ppvar[%d*_STRIDE]\ \n#endif\ \n\n", tqitem_index); Lappendstr(defs_list, buf); } if (net_send_delivered_) { insertstr(net_send_delivered_, "\ \n#if !NET_RECEIVE_BUFFERING\ \n if (_lflag == 1. ) {*(_tqitem) = 0;}\ \n#endif\ \n"); } } if (net_receive_) { Lappendstr(defs_list, "void _net_receive(Point_process*, int, double);\n"); if (net_init_q1_) { Lappendstr(defs_list, "void _net_init(Point_process*, int, double);\n"); } } if (vectorize && thread_mem_init_list->next != thread_mem_init_list) { Lappendstr(defs_list, "static void _thread_mem_init(ThreadDatum*);\n"); } if (vectorize && thread_cleanup_list->next != thread_cleanup_list) { Lappendstr(defs_list, "static void _thread_cleanup(ThreadDatum*);\n"); } if (uip) { lappendstr(defs_list, "static void _update_ion_pointer(Datum*);\n"); } sprintf(buf, "\n#define _psize %d\n#define _ppsize %d\n", parraycount, ppvar_cnt); Lappendstr(defs_list, buf); Sprintf(buf, "void _%s_reg() {\n\ int _vectorized = %d;\n", modbase, vectorize); Lappendstr(defs_list, buf); q = lappendstr(defs_list, ""); Lappendstr(defs_list, "_initlists();\n"); #else Sprintf(buf, "void _%s_reg() {\n _initlists();\n", modbase); Lappendstr(defs_list, buf); #endif if (suffix[0]) { /* not "nothing" */ #if BBCORE Lappendstr(defs_list, "_mechtype = nrn_get_mechtype(_mechanism[1]);\n"); Lappendstr(defs_list, "if (_mechtype == -1) return;\n"); Lappendstr(defs_list, "_nrn_layout_reg(_mechtype, LAYOUT);\n"); ITERATE(q, useion) { sion = SYM(q); Sprintf(buf, "_%s_type = nrn_get_mechtype(\"%s_ion\");",sion->name, sion->name); Lappendstr(defs_list, buf); q=q->next->next->next; } Lappendstr(defs_list, "\n#if 0 /*BBCORE*/\n"); #endif ITERATE(q, useion) { Sprintf(buf, "\tion_reg(\"%s\", %s);\n", SYM(q)->name, STR(q->next->next->next)); Lappendstr(defs_list, buf); q = q->next->next->next; } if (diamdec) { Lappendstr(defs_list, "\t_morphology_sym = hoc_lookup(\"morphology\");\n"); } ITERATE(q, useion) { Sprintf(buf, "\t_%s_sym = hoc_lookup(\"%s_ion\");\n", SYM(q)->name, SYM(q)->name); Lappendstr(defs_list, buf); q = q->next->next->next; } #if BBCORE Lappendstr(defs_list, "\n#endif /*BBCORE*/\n"); #endif #if VECTORIZE if (point_process) { sprintf(buf, "\ _pointtype = point_register_mech(_mechanism,\n\ nrn_alloc,%s, nrn_init,\n\ hoc_nrnpointerindex,\n\ NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/\n\ %d);\n", brkpnt_str_, vectorize ? 1 + thread_data_index : 0); Lappendstr(defs_list, buf); if (destructorfunc->next != destructorfunc) { Lappendstr(defs_list, " #if 0 /*BBCORE*/\n" " register_destructor(_destructor);\n" " #endif\n" ); } }else{ sprintf(buf, "\ register_mech(_mechanism, nrn_alloc,%s, nrn_init, hoc_nrnpointerindex, %d);\n", brkpnt_str_, vectorize ? 1 + thread_data_index : 0); Lappendstr(defs_list, buf); } if (vectorize && thread_data_index) { sprintf(buf, " _extcall_thread = (ThreadDatum*)ecalloc(%d, sizeof(ThreadDatum));\n", thread_data_index); Lappendstr(defs_list, buf); if (thread_mem_init_list->next != thread_mem_init_list) { Lappendstr(defs_list, " _thread_mem_init(_extcall_thread);\n"); if (gind) {Lappendstr(defs_list, " _thread1data_inuse = 0;\n");} } } if (vectorize) { insertstr(extra_pragma_loop_arg, "\n#define _thread_present_ /**/"); if (thread_data_index) { sprintf(buf, ", _thread[0:%d]", thread_data_index); insertstr(extra_pragma_loop_arg, buf); } ITERATE(q, acc_present_list) { insertstr(extra_pragma_loop_arg, STR(q)); } insertstr(extra_pragma_loop_arg, "\n"); } #endif #if !BBCORE Lappendstr(defs_list, "_mechtype = nrn_get_mechtype(_mechanism[1]);\n"); lappendstr(defs_list, " _nrn_setdata_reg(_mechtype, _setdata);\n"); #endif if (vectorize && thread_mem_init_list->next != thread_mem_init_list) { lappendstr(defs_list, " _nrn_thread_reg1(_mechtype, _thread_mem_init);\n"); } if (vectorize && thread_cleanup_list->next != thread_cleanup_list) { lappendstr(defs_list, " _nrn_thread_reg0(_mechtype, _thread_cleanup);\n"); } if (uip) { #if !BBCORE lappendstr(defs_list, " _nrn_thread_reg2(_mechtype, _update_ion_pointer);\n"); #endif } if (emit_check_table_thread) { lappendstr(defs_list, " _nrn_thread_table_reg(_mechtype, _check_table_thread);\n"); } if (use_bbcorepointer) { lappendstr(defs_list, " hoc_reg_bbcore_read(_mechtype, bbcore_read);\n"); lappendstr(defs_list, " hoc_reg_bbcore_write(_mechtype, bbcore_write);\n"); } sprintf(buf, " hoc_register_prop_size(_mechtype, _psize, _ppsize);\n"); Lappendstr(defs_list, buf); if (ppvar_semantics_) ITERATE(q, ppvar_semantics_) { sprintf(buf, " hoc_register_dparam_semantics(_mechtype, %d, \"%s\");\n", (int)q->itemtype, q->element.str); Lappendstr(defs_list, buf); } /* Models that write concentration need their INITIAL blocks called before those that read the concentration or reversal potential. */ i = 0; ITERATE(q, useion) { ITERATE(q1, LST(q->next->next)) { int type; type = iontype(SYM(q1)->name, SYM(q)->name); if (type == IONIN || type == IONOUT) { i += 1; } } q = q->next->next->next; } if (i) { Lappendstr(defs_list, "\tnrn_writes_conc(_mechtype, 0);\n"); } #if CVODE printf("cvode_emit=%d cvode_not_allowed=%d\n", cvode_emit, cvode_not_allowed); if (cvode_emit) { Lappendstr(defs_list,"\ hoc_register_cvode(_mechtype, _ode_count, _ode_map, _ode_spec, _ode_matsol);\n"); Lappendstr(defs_list,"\ hoc_register_tolerance(_mechtype, _hoc_state_tol, &_atollist);\n"); if (ion_synonym) { Lappendstr(defs_list, " hoc_register_synonym(_mechtype, _ode_synonym);\n"); } }else if (0 && cvode_not_allowed) { Lappendstr(defs_list, "\ hoc_register_cvode(_mechtype, _ode_count, 0, 0, 0);\n"); } if (singlechan_) { sprintf(buf, "hoc_reg_singlechan(_mechtype, _singlechan_declare%d);\n", singlechan_); Lappendstr(defs_list, buf); } #endif if (artificial_cell) { if (brkpnt_exists || !net_receive_ || nrnpointers->next != nrnpointers || useion->next != useion ) { printf( "Notice: ARTIFICIAL_CELL is a synonym for POINT_PROCESS which hints that it\n\ only affects and is affected by discrete events. As such it is not\n\ located in a section and is not associated with an integrator\n" ); } sprintf(buf, "add_nrn_artcell(_mechtype, %d);\n", tqitem_index); Lappendstr(defs_list, buf); } if (net_event_seen_) { Lappendstr(defs_list, "add_nrn_has_net_event(_mechtype);\n"); } if (watch_seen_) { Lappendstr(defs_list, "hoc_register_watch_check(_nrn_watch_check, _mechtype);\n"); } if (net_receive_buffering_) { Lappendstr(defs_list, "\ \n#if NET_RECEIVE_BUFFERING\ \n hoc_register_net_receive_buffering(_net_buf_receive, _mechtype);\ \n#endif\ \n"); if (net_send_seen_ || net_event_seen_) { Lappendstr(defs_list, "\ \n#if NET_RECEIVE_BUFFERING\ \n hoc_register_net_send_buffering(_mechtype);\ \n#endif\ \n"); } } if (net_receive_) { if (net_init_q1_) { sprintf(buf, "set_pnt_receive(_mechtype, _net_receive, _net_init, %d);\n", net_receive_); } else { sprintf(buf, "set_pnt_receive(_mechtype, _net_receive, nullptr, %d);\n", net_receive_); } Lappendstr(defs_list, buf); } if (for_netcons_) { sprintf(buf, "add_nrn_fornetcons(_mechtype, _fnc_index);\n"); Lappendstr(defs_list, buf); } q = ba_list_; for (i = 1; i <= ba_index_; ++i) { List* lst; q = q->next; #if 0 if (electrode_current) { insertstr(ITM(q), " \ #if EXTRACELLULAR\n\ if (_nd->_extnode) {\n\ v = NODEV(_nd) +_nd->_extnode->_v[0];\n\ }else\n\ #endif\n\ {\n\ v = NODEV(_nd);\n\ }\n"); }else{ insertstr(ITM(q), " v = NODEV(_nd);\n"); } #endif lst = get_ion_variables(0); if (lst->next != lst->prev) { move(lst->next, lst->prev, ITM(q)); freelist(lst); } q = q->next; lst = set_ion_variables(0); if (lst->next != lst->prev) { move(lst->next, lst->prev, ITM(q)); freelist(lst); } q = q->next; sprintf(buf, "\thoc_reg_ba(_mechtype, _ba%d, %s);\n", i, STR(q)); Lappendstr(defs_list, buf); } if (ldifuslist) { Lappendstr(defs_list, "\thoc_register_ldifus1(_difusfunc);\n"); Linsertstr(defs_list, "static void _difusfunc(ldifusfunc2_t, NrnThread*);\n"); } } /* end of not "nothing" */ #if BBCORE Lappendstr(defs_list, "\ hoc_register_var(hoc_scdoub, hoc_vdoub, NULL);\n"); #else Lappendstr(defs_list, "\ hoc_register_var(hoc_scdoub, hoc_vdoub, hoc_intfunc);\n"); #endif #if !BBCORE if (GETWD(buf)) { char buf1[NRN_BUFSIZE]; #if defined(MINGW) { char* cp; for (cp = buf; *cp; ++cp) { if (*cp == '\\') { *cp = '/'; } } } #endif sprintf(buf1, "\tivoc_help(\"help ?1 %s %s/%s\\n\");\n", mechname, buf, finname); Lappendstr(defs_list, buf1); } if (suffix[0]) { Lappendstr(defs_list, "hoc_register_limits(_mechtype, _hoc_parm_limits);\n"); Lappendstr(defs_list, "hoc_register_units(_mechtype, _hoc_parm_units);\n"); } #endif Lappendstr(defs_list, "}\n"); /* end of _reg */ if (vectorize && thread_mem_init_list->next != thread_mem_init_list) { Lappendstr(procfunc, "\nstatic void _thread_mem_init(ThreadDatum* _thread) {\n"); move(thread_mem_init_list->next, thread_mem_init_list->prev, procfunc); Lappendstr(procfunc, "}\n"); } if (vectorize && thread_cleanup_list->next != thread_cleanup_list) { Lappendstr(procfunc, "\nstatic void _thread_cleanup(ThreadDatum* _thread) {\n"); move(thread_cleanup_list->next, thread_cleanup_list->prev, procfunc); Lappendstr(procfunc, "}\n"); } if (uip) { move(uip->next, uip->prev, procfunc); } if (destructorfunc->next != destructorfunc) { if (vectorize) { Lappendstr(procfunc, "\n\ #if 0 /*BBCORE*/\n\ static _destructor(_prop)\n\ Prop *_prop; double* _p; Datum* _ppvar; ThreadDatum* _thread;\n\ {\n\ _thread = (Datum*)0;\n\ _p = prop->param; _ppvar = _prop->dparam;\n\ {\n\ "); }else{ Lappendstr(procfunc, "\n\ #if 0 /*BBCORE*/\n\ static void _destructor(Prop* _prop) {\n\ _p = _prop->param; _ppvar = _prop->dparam;\n\ {\n\ "); } movelist(destructorfunc->next, destructorfunc->prev, procfunc); Lappendstr(procfunc, "\n}\n}\n#endif /*BBCORE*/\n"); } if (ldifuslist) { ldifusreg(); } if (watch_seen_) { emit_nrn_watch_check_code(); } SYMLISTITER { s = SYM(q); if ((s->subtype & PARM)) { warn_ignore(s); } } } void warn_ignore(s) Symbol* s; { int b; double d1, d2; b = 0; if (s->nrntype & (NRNEXTRN | NRNPRANGEIN | NRNPRANGEOUT)) b = 1; if (strcmp(s->name, "v") == 0) b = 1; decode_ustr(s, &d1, &d2, buf); if (d1 == 0.0) b = 0; if (b) { printf("Warning: Default %g of PARAMETER %s will be ignored and set by NEURON.\n", d1, s->name); } } void ldifusreg() { Item* q, *qdexp, *qb1, *qvexp, *qb2, *q1; char* cfindex, *dfdcur; Symbol* s, *d; int n; /* ldifuslist format: series of symbol qdexp qb1 svexp qb2 indexforflux dflux/dconc */ n = 0; ITERATE(q, ldifuslist) { s = SYM(q); q = q->next; qdexp = ITM(q); q = q->next; qb1 = ITM(q); q = q->next; qvexp = ITM(q); q = q->next; qb2 = ITM(q); q = q->next; cfindex = STR(q); q = q->next; dfdcur = STR(q); ++n; sprintf(buf, "static void* _difspace%d;\nextern double nrn_nernst_coef();\n\ static double _difcoef%d(int _i, double* _p, Datum* _ppvar, double* _pdvol, double* _pdfcdc, ThreadDatum* _thread, NrnThread* _nt) {\n \ *_pdvol = ", n, n); lappendstr(procfunc, buf); for (q1 = qvexp; q1 != qb2; q1 = q1->next) { lappenditem(procfunc, q1); } if (dfdcur[0]) { sprintf(buf, ";\n\ if (_i == %s) {\n *_pdfcdc = %s;\n }else{ *_pdfcdc=0.;}\n", cfindex, dfdcur); }else{ sprintf(buf, "; *_pdfcdc=0.;\n"); } lappendstr(procfunc, buf); lappendstr(procfunc, " return"); for (q1 = qdexp; q1 != qb1; q1 = q1->next) { lappenditem(procfunc, q1); } lappendstr(procfunc, ";\n}\n"); } #if MAC lappendstr(procfunc, "static void _difusfunc(_f, _nt) void *_f; NrnThread* _nt; {int _i;\n"); #else lappendstr(procfunc, "static void _difusfunc(_f, _nt) void(*_f)(); NrnThread* _nt; {int _i;\n"); #endif n = 0; ITERATE(q, ldifuslist) { s = SYM(q); q = q->next; qdexp = ITM(q); q = q->next; qb1 = ITM(q); q = q->next; qvexp = ITM(q); q = q->next; qb2 = ITM(q); q = q->next; cfindex = STR(q); q = q->next; dfdcur = STR(q); ++n; if (s->subtype & ARRAY) { #if MAC sprintf(buf, " for (_i=0; _i < %d; ++_i) mac_difusfunc(_f, _mechtype, _difcoef%d, &_difspace%d, _i, ", s->araydim, n, n); #else sprintf(buf, " for (_i=0; _i < %d; ++_i) (*_f)(_mechtype, _difcoef%d, &_difspace%d, _i, ", s->araydim, n, n); #endif }else{ #if MAC sprintf(buf, " mac_difusfunc(_f,_mechtype, _difcoef%d, &_difspace%d, 0, ", n, n); #else sprintf(buf, " (*_f)(_mechtype, _difcoef%d, &_difspace%d, 0, ", n, n); #endif } lappendstr(procfunc, buf); sprintf(buf, "D%s", s->name); d = lookup(buf); assert(d); if (s->nrntype & IONCONC) { sprintf(buf, "%d, %d", - (s->ioncount_ + 1), d->varnum); }else{ sprintf(buf, "%d, %d", s->varnum, d->varnum); } lappendstr(procfunc, buf); lappendstr(procfunc, ", _nt);\n"); } lappendstr(procfunc, "}\n"); } static int decode_limits(sym, pg1, pg2) Symbol *sym; double *pg1, *pg2; { int i; double d1; if (sym->subtype & PARM) { char* cp; int n; assert(sym->u.str); for (n=0, cp = sym->u.str; *cp; ++cp) { if (*cp == '\n') { ++n; if (n == 3) { ++cp; break; } } } i = sscanf(cp, "%lf %lf\n", pg1, pg2); if (i == 2) { return 1; } } return 0; } static int decode_tolerance(sym, pg1) Symbol *sym; double *pg1; { int i; double d1; if (sym->subtype & STAT) { char* cp; int n; for (n=0, cp = sym->u.str; *cp; ++cp) { if (*cp == '\n') { ++n; if (n == 3) { ++cp; break; } } } i = sscanf(cp, "%lf\n", pg1); if (i == 1) { return 1; } } return 0; } void decode_ustr(sym, pg1, pg2, s) /* decode sym->u.str */ Symbol *sym; char *s; double *pg1, *pg2; { int i, n; char *cp, *cp1; switch (sym->subtype & (INDEP | DEP | STAT | PARM)) { case INDEP: /* but doesnt get all info */ case DEP: case STAT: assert(sym && sym->u.str); if (sym->subtype & ARRAY) { /* see parsact.c */ i = sscanf(sym->u.str, "[%*d]\n%lf%*c%lf", pg1, pg2); }else{ i = sscanf(sym->u.str, "%lf%*c%lf", pg1, pg2); } assert(i == 2); for (n=0, cp = sym->u.str; n < 2;) { if (*cp++ == '\n') { n++; } } for (cp1 = s; *cp != '\n';) { *cp1++ = *cp++; } *cp1 = '\0'; break; case PARM: assert(sym && sym->u.str); if (sym->subtype & ARRAY) { /* see parsact.c */ i = sscanf(sym->u.str, "[%*d]\n%lf\n%s", pg1, s); }else{ i = sscanf(sym->u.str, "%lf\n%s", pg1, s); } if (i == 1) { s[0] = '\0'; i = 2; } assert(i == 2); break; default: diag(sym->name, " does not have a proper declaration"); } if (s[0] == '0') {s[0] = '\0';} } void units_reg() { Symbol* s; Item* q; double d1, d2; char u[NRN_BUFSIZE]; Lappendstr(defs_list, "static HocParmUnits _hoc_parm_units[] = {\n"); ITERATE (q, syminorder) { s = SYM(q); if (s->nrntype & NRNGLOBAL) { decode_ustr(s, &d1, &d2, u); if (u[0]) { sprintf(buf, "\"%s%s\", \"%s\",\n", s->name, suffix, u); lappendstr(defs_list, buf); } } } ITERATE (q, rangeparm) { s = SYM(q); decode_ustr(s, &d1, &d2, u); if (u[0]) { sprintf(buf, "\"%s%s\", \"%s\",\n", s->name, rsuffix, u); lappendstr(defs_list, buf); } } ITERATE (q, rangestate) { s = SYM(q); decode_ustr(s, &d1, &d2, u); if (u[0]) { sprintf(buf, "\"%s%s\", \"%s\",\n", s->name, rsuffix, u); lappendstr(defs_list, buf); } } ITERATE (q, rangedep) { s = SYM(q); decode_ustr(s, &d1, &d2, u); if (u[0]) { sprintf(buf, "\"%s%s\", \"%s\",\n", s->name, rsuffix, u); lappendstr(defs_list, buf); } } ITERATE (q, nrnpointers) { s = SYM(q); decode_ustr(s, &d1, &d2, u); if (u[0]) { sprintf(buf, "\"%s%s\", \"%s\",\n", s->name, rsuffix, u); lappendstr(defs_list, buf); } } Lappendstr(defs_list, "0,0\n};\n"); } static void var_count(s) Symbol *s; { defs_h(s); s->used = varcount++; s->varnum = parraycount; if (s->subtype & ARRAY) { parraycount += s->araydim; }else{ parraycount++; } } static void defs_h(s) Symbol *s; { Item *q; if (s->subtype & ARRAY) { Sprintf(buf, "#define %s (_p + %d*_STRIDE)\n", s->name, parraycount); q = lappendstr(defs_list, buf); } else { Sprintf(buf, "#define %s _p[%d*_STRIDE]\n", s->name, parraycount); q = lappendstr(defs_list, buf); } q->itemtype = VERBATIM; } void nrn_list(q1, q2) Item *q1, *q2; { List **plist = (List **)0; Item *q; switch (SYM(q1)->type) { case RANGE: plist = (List **)0; for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->nrntype |= NRNRANGE; } break; case SUFFIX: plist = (List **)0; mechname = SYM(q2)->name; if (strcmp(SYM(q1)->name, "POINT_PROCESS") == 0) { point_process = 1; }else if (strcmp(SYM(q1)->name, "ARTIFICIAL_CELL") == 0) { point_process = 1; artificial_cell = 1; } set_suffix(); break; case ELECTRODE_CURRENT: electrode_current = 1; case NONSPECIFIC: plist = ¤ts; for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->nrntype |= NRNRANGE; } break; case SECTION: diag("NEURON SECTION variables not implemented", (char *)0); break; case GLOBAL: for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->nrntype |= NRNGLOBAL | NRNNOTP; } plist = (List **)0; break; case EXTERNAL: #if VECTORIZE threadsafe("Use of EXTERNAL is not thread safe."); #endif for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->nrntype |= NRNEXTRN | NRNNOTP; } plist = (List **)0; break; case POINTER: threadsafe("Use of POINTER is not thread safe."); plist = &nrnpointers; for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->nrntype |= NRNNOTP | NRNPOINTER; } break; case BBCOREPOINTER: threadsafe("Use of BBCOREPOINTER is not thread safe."); plist = &nrnpointers; for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->nrntype |= NRNNOTP | NRNBBCOREPOINTER; } use_bbcorepointer = 1; break; } if (plist) { if (!*plist) { *plist = newlist(); } assert (q1 != q2); movelist(q1->next, q2, *plist); } } void bablk(ba, type, q1, q2) int ba, type; Item *q1, *q2; { Item* qb, *qv, *q; qb = insertstr(q1->prev->prev, "/*"); insertstr(q1, "*/\n"); if (!ba_list_) { ba_list_ = newlist(); } sprintf(buf, "static void _ba%d(NrnThread* _nt, Memb_list* _ml, int _type) ", ++ba_index_); insertstr(q1, buf); q = q1->next; qv = insertstr(q, "" " double* _p; Datum* _ppvar; ThreadDatum* _thread;\n" " int* _ni; double v; int _iml, _cntml_padded, _cntml_actual;\n" " _cntml_actual = _ml->_nodecount;\n" " _cntml_padded = _ml->_nodecount_padded;\n" " _ni = _ml->_nodeindices;\n" " _thread = _ml->_thread;\n" " double * _nt_data = _nt->_data;\n" " double * _vec_v = _nt->_actual_v;\n" " int stream_id = _nt->stream_id;\n" " #if LAYOUT == 1 /*AoS*/\n" " for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n" " _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n" " #elif LAYOUT == 0 /*SoA*/\n" " _p = _ml->_data; _ppvar = _ml->_pdata;\n" " /* insert compiler dependent ivdep like pragma */\n" " _PRAGMA_FOR_VECTOR_LOOP_\n" " _PRAGMA_FOR_STATE_ACC_LOOP_\n" " for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n" " #else /* LAYOUT > 1 */ /*AoSoA*/\n" " #error AoSoA not implemented.\n" " for (;;) { /* help clang-format properly indent */\n" " #endif\n" " v = _vec_v[_ni[_iml]];\n" ); insertstr(q2, "}\n"); movelist(qb, q2, procfunc); ba = (ba == BEFORE) ? 10 : 20; /* BEFORE or AFTER */ ba += (type == BREAKPOINT) ? 1 : 0; ba += (type == SOLVE) ? 2 : 0; ba += (type == INITIAL1) ? 3 : 0; ba += (type == STEP) ? 4 : 0; lappenditem(ba_list_, qv->next); lappenditem(ba_list_, q2); sprintf(buf, "%d", ba); lappendstr(ba_list_, buf); } int ion_declared(Symbol* s) { Item* q; int used = 0; ITERATE(q, useion) { if (SYM(q) == s) { used = 1; } q = q->next->next->next; } return used; } void nrn_use(q1, q2, q3, q4) Item *q1, *q2, *q3, *q4; { int used, i; Item *q, *qr, *qw; List *readlist, *writelist; Symbol *ion; ion = SYM(q1); /* is it already used */ used = ion_declared(SYM(q1)); if (used) { /* READ gets promoted to WRITE */ diag("mergeing of neuron models not supported yet", (char *)0); }else{ /* create all the ionic variables */ Lappendsym(useion, ion); readlist = newlist(); writelist = newlist(); qr = lappendsym(useion, SYM0); qw = lappendsym(useion, SYM0); if (q4) { lappendstr(useion, STR(q4)); }else{ lappendstr(useion, "-10000."); } LST(qr) = readlist; LST(qw) = writelist; if (q2) { Item *qt = q2->next; move(q1->next->next, q2, readlist); if (q3) { move(qt->next, q3, writelist); } }else if (q3) { move(q1->next->next, q3, writelist); } ITERATE(q, readlist) { i = iontype(SYM(q)->name, ion->name); if (i == IONCUR) { SYM(q)->nrntype |= NRNCURIN; }else{ SYM(q)->nrntype |= NRNPRANGEIN; if (i == IONIN || i == IONOUT) { SYM(q)->nrntype |= IONCONC; } } } ITERATE(q, writelist) { i = iontype(SYM(q)->name, ion->name); if (i == IONCUR) { if (!currents) { currents = newlist(); } Lappendsym(currents, SYM(q)); SYM(q)->nrntype |= NRNCUROUT; }else{ SYM(q)->nrntype |= NRNPRANGEOUT; if (i == IONIN || i == IONOUT) { SYM(q)->nrntype |= IONCONC; } } } } } static int iontype(s1, s2) /* returns index of variable in ion mechanism */ char *s1, *s2; { Sprintf(buf, "i%s", s2); if (strcmp(buf, s1) == 0) { return IONCUR; } Sprintf(buf, "e%s", s2); if (strcmp(buf, s1) == 0) { return IONEREV; } Sprintf(buf, "%si", s2); if (strcmp(buf, s1) == 0) { return IONIN; } Sprintf(buf, "%so", s2); if (strcmp(buf, s1) == 0) { return IONOUT; } Sprintf(buf, "%s is not a valid ionic variable for %s", s1, s2); diag(buf, (char *)0); return -1; } static Symbol *ifnew_install(name) char *name; { Symbol *s; if ((s = lookup(name)) == SYM0) { s = install(name, NAME); parminstall(s, "0", "", ""); } return s; } static void nrndeclare() { Symbol *s; Item *q; s=lookup("diam"); if (s) { if (s->nrntype & (NRNRANGE|NRNGLOBAL)) { diag(s->name, " cannot be a RANGE or GLOBAL variable for this mechanism"); } s->nrntype |= NRNNOTP|NRNPRANGEIN; diamdec=1; } s=lookup("area"); if (s) { if (s->nrntype & (NRNRANGE|NRNGLOBAL)) { diag(s->name, " cannot be a RANGE or GLOBAL variable for this mechanism"); } s->nrntype |= NRNNOTP|NRNPRANGEIN; areadec=1; } #if VECTORIZE if (vectorize) { s = ifnew_install("v"); s->nrntype = NRNNOTP; /* this is a lie, it goes in at end specially */ /* no it is not a lie. Use an optimization where voltage passed via arguments */ }else #endif { s = ifnew_install("v"); s->nrntype |= NRNSTATIC | NRNNOTP; } s = ifnew_install("t"); s->nrntype |= NRNEXTRN | NRNNOTP; s = ifnew_install("dt"); s->nrntype |= NRNEXTRN | NRNNOTP; vectorize_substitute(lappendstr(defs_list, "\n#define t nrn_threads->_t\n#define dt nrn_threads->_dt\n"), "\n#define t _nt->_t\n#define dt _nt->_dt\n"); s=lookup("usetable"); if (s) { s->nrntype |= NRNGLOBAL | NRNNOTP;} s=lookup("celsius");if(s){s->nrntype |= NRNEXTRN | NRNNOTP;} s=lookup("celcius"); if (s) diag("celcius should be spelled celsius", (char *)0); ITERATE(q, syminorder) { s = SYM(q); if (s->type == NAME || s->type == PRIME) { if (s->subtype & PARM && s->nrntype & NRNRANGE) { Lappendsym(rangeparm, s); } else if (s->subtype & STAT) { s->nrntype |= NRNRANGE; Lappendsym(rangestate, s); } else if (s->subtype & DEP && s->nrntype & NRNRANGE) { Lappendsym(rangedep, s); } if (s != indepsym && !s->nrntype) { if (s->subtype & PARM) { if (s->usage & EXPLICIT_DECL) { s->nrntype |= NRNGLOBAL; s->nrntype |= NRNNOTP; }else{ s->nrntype |= NRNSTATIC; s->nrntype |= NRNNOTP; } } } } } /* some ionic variables don't need duplicates known to hoc */ del_range(rangeparm); del_range(rangestate); del_range(rangedep); } static void del_range(range) List *range; { Item *q, *q1; Symbol *s; for (q = ((Item *)range)->next; q != (Item *)range; q = q1) { q1 = q->next; s = SYM(q); if (s->nrntype & (NRNPRANGEIN | NRNPRANGEOUT)) { delete(q); } } } static void declare_p() { Item *q; Symbol* s; int pcs = 0; ITERATE(q, syminorder) { SYM(q)->used = -1; } ITERATE(q, rangeparm) { var_count(SYM(q)); } ITERATE(q, rangedep) { var_count(SYM(q)); } ITERATE(q, rangestate) { var_count(SYM(q)); } ITERATE(q, syminorder) { if (!(SYM(q)->nrntype & NRNNOTP) && SYM(q)->used < 0) { var_count(SYM(q)); } } #if VECTORIZE if (vectorize) { s = ifnew_install("_v_unused"); var_count(s); pcs = 1; } #endif if (brkpnt_exists) { if (vectorize) { s = ifnew_install("_g_unused"); var_count(s); pcs = 2; }else{ s = ifnew_install("_g"); var_count(s); } } if (debugging_ && net_receive_) { s = ifnew_install("_tsav"); var_count(s); } if (pcs) { sprintf(buf, "\ \n#ifndef NRN_PRCELLSTATE\ \n#define NRN_PRCELLSTATE 0\ \n#endif\ \n#if NRN_PRCELLSTATE\ \n#define _PRCELLSTATE_V _v_unused = _v;\ \n#define _PRCELLSTATE_G %s\ \n#else\ \n#define _PRCELLSTATE_V /**/\ \n#define _PRCELLSTATE_G /**/\ \n#endif\ \n", (pcs == 2) ? "_g_unused = _g;" : "/**/"); Lappendstr(defs_list, buf); } } List *set_ion_variables(block) int block; /* 0 means equation block , 2 means initial block */ { /*ARGSUSED*/ Item *q, *q1, *qconc; char* in; static List *l; int declared = 0; l = newlist(); ITERATE(q, useion) { in = SYM(q)->name; q = q->next; q = q->next; qconc = (Item*)0; ITERATE(q1, LST(q)) { if (SYM(q1)->nrntype & NRNCUROUT) { if ( block == 0) { Sprintf(buf, " _ion_%s += %s", SYM(q1)->name, breakpoint_current(SYM(q1))->name); Lappendstr(l, buf); if (point_process) { Sprintf(buf, "* 1.e2/ (_nd_area);\n"); }else{ Sprintf(buf, ";\n"); } }else{ buf[0] = '\0'; } }else{ if (iontype(SYM(q1)->name, in) != IONEREV) { qconc = q1; } Sprintf(buf, " _ion_%s = %s;\n", SYM(q1)->name, SYM(q1)->name); } Lappendstr(l, buf); } q = q->next; /* when INITIAL block is called, if it modifies the concentrations then the reversal potential should be recomputed in case other mechanisms need the true initial value. This would be rare since most initial blocks do not depend on erev. Instead the right value will be present due to fcurrent or cvode f(y). However, this fastidiousness cant hurt. It just makes ion_style in effect always at least for initialization. */ /* sure enough, someone needed to demote the ion_style so that erev is decoupled from concentrations. So we need another variable pointing to the ionstyle */ if (block == 2 && qconc) { int ic = iontype(SYM(qconc)->name, in); if (ic == IONIN) { ic = 1; }else if (ic == IONOUT) { ic = 2; }else{ assert(0); } /* first arg is for the charge and memb_list, second and third give * pointer to erev, fourth arg is the style, seventh needed for figuring * out _cntml if SoA. Note 2nd argument added as pe because we see errors * with pointer arithmetic in OpenACC cray compiler */ Sprintf(buf, " %s _pe = (&(_ion_%s));\n", declared ? "" : "double*", SYM(qconc)->name); Lappendstr(l, buf); Sprintf(buf, " Memb_list* _%s_ml;\n", in); Lappendstr(l, buf); Sprintf(buf, " _%s_ml = _nt->_ml_list[_%s_type];\n", in, in); Lappendstr(l, buf); Sprintf(buf, " %s _tmp_cntml = _%s_ml->_nodecount_padded;\n", declared ? "" : "int", in); declared = 1; Lappendstr(l, buf); Sprintf(buf, " nrn_wrote_conc(_%s_type, _pe, %d, _style_%s, nrn_ion_global_map, celsius, _tmp_cntml);\n", in, ic, in); Lappendstr(l, buf); } } return l; } List *get_ion_variables(block) int block; /* 0 means equation block */ /* 2 means ode_spec and ode_matsol blocks */ { /*ARGSUSED*/ Item *q, *q1; static List *l; l = newlist(); ITERATE(q, useion) { q = q->next; ITERATE(q1, LST(q)) { if (block == 2 && (SYM(q1)->nrntype & IONCONC) && (SYM(q1)->subtype & STAT)) { continue; } Sprintf(buf, " %s = _ion_%s;\n", SYM(q1)->name, SYM(q1)->name); Lappendstr(l, buf); if (point_process && (SYM(q1)->nrntype & NRNCURIN)) { Fprintf(stderr, "WARNING: Dimensions may be wrong for READ %s with POINT_PROCESS\n", SYM(q1)->name); } } q = q->next; ITERATE(q1, LST(q)) { if (block == 2 && (SYM(q1)->nrntype & IONCONC) && (SYM(q1)->subtype & STAT)) { continue; } if (SYM(q1)->nrntype & IONCONC) { Sprintf(buf, " %s = _ion_%s;\n", SYM(q1)->name, SYM(q1)->name); Lappendstr(l, buf); } if (SYM(q1)->subtype & STAT) { if (SYM(q1)->nrntype & NRNCUROUT) { Fprintf(stderr, "WARNING: WRITE %s with it a STATE may not be translated correctly\n", SYM(q1)->name); } } } q = q->next; } return l; } /* note: _nt_data is only defined in nrn_init, nrn_cur and nrn_state where ions are used in the current mod files */ static int iondef(p_pointercount) int *p_pointercount; { int ioncount, it, need_style; Item *q, *q1, *q2; Symbol *sion; char ionname[100]; ioncount = 0; if (point_process) { ioncount = 2; q = lappendstr(defs_list, "#define _nd_area _nt_data[_ppvar[0*_STRIDE]]\n"); q->itemtype = VERBATIM; ppvar_semantics(0, "area"); ppvar_semantics(1, "pntproc"); } ITERATE(q, useion) { int dcurdef = 0; if (!uip) { uip = newlist(); lappendstr(uip, "static void _update_ion_pointer(Datum* _ppvar) {\n"); } need_style = 0; sion = SYM(q); sprintf(ionname, "%s_ion", sion->name); q=q->next; ITERATE(q1, LST(q)) { SYM(q1)->nrntype |= NRNIONFLAG; Sprintf(buf, "#define _ion_%s _nt_data[_ppvar[%d*_STRIDE]]\n", SYM(q1)->name, ioncount); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; sprintf(buf, " nrn_update_ion_pointer(_%s_sym, _ppvar, %d, %d);\n", sion->name, ioncount, iontype(SYM(q1)->name, sion->name)); #if 0 /*BBCORE*/ lappendstr(uip, buf); #endif /*BBCORE*/ SYM(q1)->ioncount_ = ioncount; ppvar_semantics(ioncount, ionname); ioncount++; } q=q->next; ITERATE(q1, LST(q)) { if (SYM(q1)->nrntype & NRNIONFLAG) { SYM(q1)->nrntype &= ~NRNIONFLAG; }else{ Sprintf(buf, "#define _ion_%s _nt_data[_ppvar[%d*_STRIDE]]\n", SYM(q1)->name, ioncount); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; sprintf(buf, " nrn_update_ion_pointer(_%s_sym, _ppvar, %d, %d);\n", sion->name, ioncount, iontype(SYM(q1)->name, sion->name)); #if 0 /*BBCORE*/ lappendstr(uip, buf); #endif /*BBCORE*/ SYM(q1)->ioncount_ = ioncount; ppvar_semantics(ioncount, ionname); ioncount++; } it = iontype(SYM(q1)->name, sion->name); if (it == IONCUR) { dcurdef = 1; Sprintf(buf, "#define _ion_di%sdv\t_nt_data[_ppvar[%d*_STRIDE]]\n", sion->name, ioncount); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; sprintf(buf, " nrn_update_ion_pointer(_%s_sym, _ppvar, %d, 4);\n", sion->name, ioncount); #if 0 /*BBCORE*/ lappendstr(uip, buf); #endif /*BBCORE*/ ppvar_semantics(ioncount, ionname); ioncount++; } if (it == IONIN || it == IONOUT) { /* would have wrote_ion_conc */ need_style = 1; } } if (need_style) { Sprintf(buf, "#define _style_%s\t_ppvar[%d]\n", sion->name, ioncount); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; sprintf(buf, "#%s", ionname); ppvar_semantics(ioncount, buf); ioncount++; } q=q->next; if (!dcurdef && ldifuslist) { Sprintf(buf, "#define _ion_di%sdv\t_nt_data[_ppvar[%d*_STRIDE]]\n", sion->name, ioncount); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; sprintf(buf, " nrn_update_ion_pointer(_%s_sym, _ppvar, %d, 4);\n", sion->name, ioncount); #if 0 /*BBCORE*/ lappendstr(uip, buf); #endif /*BBCORE*/ ppvar_semantics(ioncount, ionname); ioncount++; } } *p_pointercount = 0; ITERATE(q, nrnpointers) { sion = SYM(q); if (sion->nrntype & NRNPOINTER) { Sprintf(buf, "#define %s _nt->_data[_ppvar[%d*_STRIDE]]\n", sion->name, ioncount + *p_pointercount); ppvar_semantics(ioncount + *p_pointercount, "pointer"); } if (sion->nrntype & NRNBBCOREPOINTER) { Sprintf(buf, "#define _p_%s _nt->_vdata[_ppvar[%d*_STRIDE]]\n", sion->name, ioncount + *p_pointercount); ppvar_semantics(ioncount + *p_pointercount, "bbcorepointer"); } sion->used = ioncount + *p_pointercount; q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; (*p_pointercount)++; } if (diamdec) { /* must be last */ Sprintf(buf, "#define diam _nt->_data[_ppvar[%d*_STRIDE]]\n", ioncount + *p_pointercount); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; } /* notice that ioncount is not incremented */ if (areadec) { /* must be last, if we add any more the administrative procedures must be redone */ Sprintf(buf, "#define area _nt->_data[_ppvar[%d*_STRIDE]]\n", ioncount+ *p_pointercount + diamdec); q2 = lappendstr(defs_list, buf); q2->itemtype = VERBATIM; } /* notice that ioncount is not incremented */ if (uip) { lappendstr(uip, "}\n"); } return ioncount; } void ppvar_semantics(int i, const char* name) { Item* q; if (!ppvar_semantics_) { ppvar_semantics_ = newlist(); } q = Lappendstr(ppvar_semantics_, name); q->itemtype = (short)i; } List *begin_dion_stmt() { Item *q, *q1, *qbrak; static List *l; char *strion; l = newlist(); qbrak = lappendstr(l, "\t{"); ITERATE(q, useion) { strion = SYM(q)->name; q = q->next; q = q->next; ITERATE(q1, LST(q)) { if (SYM(q1)->nrntype & NRNCUROUT) { Sprintf(buf, " _di%s = %s;\n", strion, SYM(q1)->name); Lappendstr(l, buf); Sprintf(buf, "double _di%s;\n", strion); Insertstr(qbrak->next, buf); } } q = q->next; } return l; } List *end_dion_stmt(strdel) char *strdel; { Item *q, *q1; static List *l; char *strion; l = newlist(); ITERATE(q, useion) { strion = SYM(q)->name; q = q->next; q = q->next; ITERATE(q1, LST(q)) { if (SYM(q1)->nrntype & NRNCUROUT) { Sprintf(buf, " _ion_di%sdv += (_di%s - %s)/%s", strion, strion, SYM(q1)->name, strdel); Lappendstr(l, buf); if (point_process) { Lappendstr(l, "* 1.e2/ (_nd_area);\n"); }else{ Lappendstr(l, ";\n"); } } } q = q->next; } Lappendstr(l, "\t}\n"); return l; } static void ion_promote(qion) Item* qion; { Item* q; char* in; int conc, rev; int type; conc = 0; rev = 0; in = SYM(qion)->name; ITERATE(q, LST(qion->next)) { /* check READ */ type = iontype(SYM(q)->name, in); if (type == IONIN || type == IONOUT) { conc = 1; } if (type == IONEREV) { rev = 1; } } ITERATE(q, LST(qion->next->next)) { /* promote if WRITE */ type = iontype(SYM(q)->name, in); if (type == IONIN) { Lappendstr(defs_list, "nrn_check_conc_write(_prop, prop_ion, 1);\n"); conc = 3; } if (type == IONOUT) { Lappendstr(defs_list, "nrn_check_conc_write(_prop, prop_ion, 0);\n"); conc = 3; } if (type == IONEREV) { rev = 3; } } if (conc || rev) { Sprintf(buf, "nrn_promote(prop_ion, %d, %d);\n", conc, rev); Lappendstr(defs_list, buf); } } #define NRNFIX(arg) if (strcmp(n, arg) == 0) e=1; void nrn_var_assigned(s) Symbol* s; { int e; char* n; if (s->assigned_to_ == 0) { s->assigned_to_ = 1; } if (protect_) { s->assigned_to_ = 2; } e = 0; n = s->name; NRNFIX("area"); NRNFIX("diam"); NRNFIX("t"); NRNFIX("dt"); NRNFIX("celsius"); if (e) { diag(s->name, " is a special NEURON variable that should not be\n assigned a value\ in a model description file\n"); } } #if CVODE static int cvode_valid_, using_cvode; static int cvode_num_, cvode_neq_; static Symbol* cvode_fun_; void slist_data(s, indx, findx) Symbol* s; int indx, findx; { /* format: number of pairs, followed by findx, indx pairs */ int* pi; int i, n; if (s->slist_info_) { /* i'd use realloc but to avoid portability problems */ /* this probably will never get executed anyway */ n = s->slist_info_[0] + 1; pi = (int*)emalloc((1 + 2*n)*sizeof(int)); for (i=2*(n-1); i > 0; --i) { pi[i] = s->slist_info_[i]; } free(s->slist_info_); s->slist_info_ = pi; pi[0] = n; pi[2*n-1] = findx; pi[2*n] = indx; }else{ s->slist_info_ = pi = (int*)emalloc(3*sizeof(int)); pi[0] = 1; pi[1] = findx; pi[2] = indx; } } int slist_search(n, s) int n; Symbol* s; { int i, *pi; pi = s->slist_info_; if (pi == (int*)0) { diag(s->name, " not really a STATE; Ie. No differential equation for it.\n"); } assert(pi); for (i=0; i < pi[0]; ++i) { if (pi[1+2*i] == n) { return pi[2+2*i]; } } assert(0); return 0; } static void cvode_conc_map() { /* pv index is slist index, ppd index is to the concentration pointer to the ion concentration is eg. &(ion_cai). Unfortunately the slist index has nothing to do with the _p array index. To recover the slist index, an slist_index list was made for every slist which consists of an slist ordered list of state symbols */ /* also must handle case where user WRITE cai but cai is not a STATE since inefficiency occurs due to inability to set eca when states are predicted */ Item* q, *q1, *q2, *q3; int sindex; ITERATE(q, useion) { q = q->next; q = q->next; ITERATE(q1, LST(q)) { if (SYM(q1)->nrntype & IONCONC) { if ((SYM(q1)->subtype & STAT)) { sindex = slist_search(cvode_num_, SYM(q1)); sprintf(buf, "\t_pv[%d] = &(_ion_%s);\n", sindex, SYM(q1)->name); lappendstr(procfunc, buf); }else{ /* not a STATE but WRITE it*/ /*its got to have an assignment in a SOLVE block and that assignment better not depend on intermediate variables that depend on states because we will assign cai using only that statement prior to calling the nernst equation code. */ int b = 0; if (!ion_synonym) { ion_synonym = newlist(); } ITERATE(q2, procfunc) { if (q2->itemtype == SYMBOL && SYM(q2) == SYM(q1)) { q3 = q2->next; if (q3->itemtype == SYMBOL && strcmp(SYM(q3)->name, "=") == 0) { /*printf(" found reference to %s = ...\n", SYM(q2)->name);*/ sprintf(buf, "_ion_%s = ", SYM(q2)->name); lappendstr(ion_synonym, buf); for (q3 = q3->next; q3 != procfunc->prev; q3 = q3->next) { lappenditem(ion_synonym, q3); if (q3->itemtype == SYMBOL && SYM(q3) == semi) { #if 0 if (q3->itemtype == STRING && strchr(STR(q3), ';')) { char* e, *s = stralloc(STR(q3), (char*)0); e = strchr(s, ';'); *e = '\0'; sprintf(buf, "%s;\n", s); printf("|%s||%s||%s|\n",STR(q3), s, buf); lappendstr(ion_synonym, buf); #endif b = 1; break; } } break; } } } if (b == 0) { diag(SYM(q1)->name, " is WRITE but is not a STATE and has no assignment statement"); } } } } q = q->next; } } void out_nt_ml_frag(List* p) { vectorize_substitute(lappendstr(p, " ThreadDatum* _thread;\n"), " double* _p; Datum* _ppvar; ThreadDatum* _thread;\n"); Lappendstr(p, " Node* _nd; double _v; int _iml, _cntml_padded, _cntml_actual;\n\ _cntml_actual = _ml->_nodecount;\n\ _cntml_padded = _ml->_nodecount_padded;\n\ _thread = _ml->_thread;\n\ for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n\ _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n\ _nd = _ml->_nodelist[_iml];\n\ v = NODEV(_nd);\n\ "); } void cvode_emit_interface() { List* lst; Item* q, *q1; if (cvode_not_allowed) { Lappendstr(defs_list, "\n\ static int _ode_count(int);\n"); sprintf(buf, "\n\ static int _ode_count(int _type){ hoc_execerror(\"%s\", \"cannot be used with CVODE\"); return 0;}\n", mechname); Lappendstr(procfunc, buf); }else if (cvode_emit) { Lappendstr(defs_list, "\n\ static int _ode_count(int);\n\ static void _ode_map(int, double**, double**, double*, Datum*, double*, int);\n\ static void _ode_spec(NrnThread*, Memb_list*, int);\n\ static void _ode_matsol(NrnThread*, Memb_list*, int);\n\ "); sprintf(buf, "\n\ static int _ode_count(int _type){ return %d;}\n", cvode_neq_); Lappendstr(procfunc, buf); sprintf(buf, "\n#define _cvode_ieq _ppvar[%d]._i\n",cvode_ieq_index); Lappendstr(defs_list, buf); if (cvode_fun_->subtype == PROCED) { cvode_proced_emit(); }else{ Lappendstr(procfunc, "\nstatic void _ode_spec(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); out_nt_ml_frag(procfunc); lst = get_ion_variables(1); if (lst->next->itemtype) movelist(lst->next, lst->prev, procfunc); sprintf(buf," _ode_spec%d", cvode_num_); Lappendstr(procfunc, buf); vectorize_substitute(lappendstr(procfunc, "();\n"), "(_threadargs_);\n"); lst = set_ion_variables(1); if (lst->next->itemtype) movelist(lst->next, lst->prev, procfunc); Lappendstr(procfunc, "}}\n"); Lappendstr(procfunc, "\n\ static void _ode_map(int _ieq, double** _pv, double** _pvdot, double* _pp, Datum* _ppd, double* _atol, int _type) {"); vectorize_substitute(lappendstr(procfunc, "\n"), "\n\ double* _p; Datum* _ppvar;\n"); sprintf(buf, "\ int _i; _p = _pp; _ppvar = _ppd;\n\ _cvode_ieq = _ieq;\n\ for (_i=0; _i < %d; ++_i) {\n\ _pv[_i] = _pp + _slist%d[_i]; _pvdot[_i] = _pp + _dlist%d[_i];\n\ _cvode_abstol(_atollist, _atol, _i);\n\ }\n", cvode_neq_, cvode_num_, cvode_num_); Lappendstr(procfunc, buf); /* need to take care of case where a state is an ion concentration. Replace the _pp pointer with a pointer to the actual ion model's concentration */ cvode_conc_map(); Lappendstr(procfunc, "}\n"); if (ion_synonym) { Lappendstr(defs_list, "static void _ode_synonym(int, double**, Datum**);\n"); Lappendstr(procfunc, "\ static void _ode_synonym(int _cnt, double** _pp, Datum** _ppd) {"); vectorize_substitute(lappendstr(procfunc, "\n"), "\n\ double* _p; Datum* _ppvar;\n"); Lappendstr(procfunc, "\ int _i; \n\ for (_i=0; _i < _cnt; ++_i) {_p = _pp[_i]; _ppvar = _ppd[_i];\n"); movelist(ion_synonym->next, ion_synonym->prev, procfunc); Lappendstr(procfunc, "}}\n"); } Lappendstr(procfunc, "\nstatic void _ode_matsol(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); out_nt_ml_frag(procfunc); lst = get_ion_variables(1); if (lst->next->itemtype) movelist(lst->next, lst->prev, procfunc); if (cvode_fun_->subtype == KINF) { int i = cvode_num_; sprintf(buf, "_cvode_sparse(&_cvsparseobj%d, %d, _dlist%d, _p, _ode_matsol%d, &_coef%d);\n", i, cvode_neq_, i, i, i); Lappendstr(procfunc, buf); sprintf(buf, "_cvode_sparse_thread(&_thread[_cvspth%d]._pvoid, %d, _dlist%d, _p, _ode_matsol%d, _ppvar, _thread, _nt);\n", i, cvode_neq_, i, i); vectorize_substitute(procfunc->prev, buf); }else{ sprintf(buf, "_ode_matsol%d", cvode_num_); Lappendstr(procfunc, buf); vectorize_substitute(lappendstr(procfunc, "();\n"), "(_threadargs_);\n"); } Lappendstr(procfunc, "}}\n"); } /* handle the state_discontinuities */ if (state_discon_list_) ITERATE(q, state_discon_list_) { Symbol* s; int sindex; q1 = ITM(q); s = SYM(q1); if (q1->itemtype == SYMBOL && (s->subtype & STAT)) { sindex = slist_search(cvode_num_, s); sprintf(buf, "_cvode_ieq + %d, &", sindex); replacstr(q1->prev, buf); } } } } void cvode_proced_emit() { sprintf(buf, "\n\ static void _ode_spec(Node* _nd, double* _pp, Datum* _ppd) {\n\ _p = _pp; _ppvar = _ppd; v = NODEV(_nd);\n\ %s();\n}\n", cvode_fun_->name); Lappendstr(procfunc, buf); sprintf(buf, "\n\ static void _ode_map(int _ieq, double** _pv, doubl** _pvdot, double* _pp){}\n"); Lappendstr(procfunc, buf); Lappendstr(procfunc, "\n\ static void _ode_matsol(Node* _nd, double* _pp, Datum* _ppd){}\n"); } void cvode_interface(fun, num, neq) Symbol* fun; int num, neq; { /* if only one then allowed and emit */ cvode_valid_ = 1; cvode_not_allowed = (using_cvode++) ? 1 : 0; cvode_emit = !cvode_not_allowed; cvode_num_ = num; cvode_neq_ = neq; cvode_fun_ = fun; if (cvode_fun_->subtype == PROCED) { cvode_emit = 0; return; } Sprintf(buf, "\n\ static int _ode_spec%d(_threadargsproto_);\n\ /*static int _ode_matsol%d(_threadargsproto_);*/\n\ ", num, num); Linsertstr(procfunc, buf); } void cvode_valid() { static int once; if (!cvode_valid_ && !once++) { Fprintf(stderr, "Notice: This mechanism cannot be used with CVODE\n"); cvode_not_allowed = 1; } cvode_valid_ = 0; } void cvode_rw_cur(b) char* b; { /* if a current is READ and WRITE then call the correct _ode_spec since it may compute some aspect of the current */ Item* q, *q1; int type; Symbol* sion; b[0] = '\0'; ITERATE(q, useion) { sion = SYM(q); q = q->next; ITERATE (q1, LST(q)) { type = SYM(q1)->nrntype; if ((type & NRNCURIN) && (type & NRNCUROUT)) { if (!cvode_not_allowed && cvode_emit) { if (vectorize) { sprintf(b, "if (_nt->_vcv) { _ode_spec%d(_threadargs_); }\n", cvode_num_); }else{ sprintf(b, "if (_nt->_vcv) { _ode_spec%d(); }\n", cvode_num_); } return; } } } q = q->next; q = q->next; } } #endif const char* net_boilerplate(int flag) { char b[1000]; b[0] = '\0'; sprintf(buf, "\n\ NrnThread* _nt;\n\ int _tid = _pnt->_tid; \n\ _nt = nrn_threads + _tid;\n\ "); sprintf(b, "%s", buf); sprintf(buf, "%s\ _thread = (ThreadDatum*)0; \n\ double *_weights = _nt->_weights;\n\ _args = _weights + _weight_index;\n\ _ml = _nt->_ml_list[_pnt->_type];\n\ _cntml_actual = _ml->_nodecount;\n\ _cntml_padded = _ml->_nodecount_padded;\n\ _iml = _pnt->_i_instance;\n\ #if LAYOUT == 1 /*AoS*/\n\ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n\ #endif\n\ #if LAYOUT == 0 /*SoA*/\n\ _p = _ml->_data; _ppvar = _ml->_pdata;\n\ #endif\n\ #if LAYOUT > 1 /*AoSoA*/\n\ #error AoSoA not implemented.\n\ #endif\n\ ", b); return buf; } void emit_net_receive_buffering_code() { Item* q; if (!net_receive_buffering_) { return; } q = net_receive_block_begin_; insertstr(q, "\n#if NET_RECEIVE_BUFFERING"); sprintf(buf, "\ \n#undef t\ \n#define t _nrb_t\ \nstatic inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag);\ \nvoid _net_buf_receive(NrnThread* _nt) {\ \n if (!_nt->_ml_list) { return; }\ \n Memb_list* _ml = _nt->_ml_list[_mechtype];\ \n if (!_ml) { return; }\ \n NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer;\ "); insertstr(q, buf); sprintf(buf, "\ \n int _di;\ \n int stream_id = _nt->stream_id;\ \n Point_process* _pnt = _nt->pntprocs;\ \n int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset;\ \n int _displ_cnt = _nrb->_displ_cnt;\ \n _PRAGMA_FOR_NETRECV_ACC_LOOP_ \ \n for (_di = 0; _di < _displ_cnt; ++_di) {\ \n int _inrb;\ \n int _di0 = _nrb->_displ[_di];\ \n int _di1 = _nrb->_displ[_di + 1];\ \n for (_inrb = _di0; _inrb < _di1; ++_inrb) {\ \n int _i = _nrb->_nrb_index[_inrb];\ \n int _j = _nrb->_pnt_index[_i];\ \n int _k = _nrb->_weight_index[_i];\ \n double _nrt = _nrb->_nrb_t[_i];\ \n double _nrflag = _nrb->_nrb_flag[_i];\ \n _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag);\ \n }\ \n }\ \n #pragma acc wait(stream_id)\ \n _nrb->_displ_cnt = 0;\ \n _nrb->_cnt = 0;\ \n /*printf(\"_net_buf_receive_%s %%d\\n\", _nt->_id);*/\ \n", suffix); insertstr(q, buf); if (net_send_seen_ || net_event_seen_) { sprintf(buf, "\ \n {\ \n NetSendBuffer_t* _nsb = _ml->_net_send_buffer;\ \n#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\ \n #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu)\ \n update_net_send_buffer_on_host(_nt, _nsb);\ \n#endif\ \n int _i;\ \n for (_i=0; _i < _nsb->_cnt; ++_i) {\ \n net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i],\ \n _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i],\ \n _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]);\ \n }\ \n _nsb->_cnt = 0;\ \n#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\ \n #pragma acc update device(_nsb->_cnt) if (_nt->compute_gpu)\ \n#endif\ \n }\ \n"); insertstr(q, buf); } insertstr(q, "\n}\n"); if (net_send_seen_ || net_event_seen_) { sprintf(buf, "\ \nstatic void _net_send_buffering(NetSendBuffer_t* _nsb, int _sendtype, int _i_vdata, int _weight_index,\ \n int _ipnt, double _t, double _flag) {\ \n int _i = 0;\ \n #pragma acc atomic capture\ \n _i = _nsb->_cnt++;\ \n#if !defined(_OPENACC)\ \n if (_i >= _nsb->_size) {\ \n _nsb->grow();\ \n }\ \n#endif\ \n if (_i < _nsb->_size) {\ \n _nsb->_sendtype[_i] = _sendtype;\ \n _nsb->_vdata_index[_i] = _i_vdata;\ \n _nsb->_weight_index[_i] = _weight_index;\ \n _nsb->_pnt_index[_i] = _ipnt;\ \n _nsb->_nsb_t[_i] = _t;\ \n _nsb->_nsb_flag[_i] = _flag;\ \n }\ \n}\n"); insertstr(q, buf); } sprintf(buf, "\ \nvoid _net_receive (Point_process* _pnt, int _weight_index, double _lflag) {\ \n NrnThread* _nt = nrn_threads + _pnt->_tid;\ \n NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer;\ \n if (_nrb->_cnt >= _nrb->_size){\ \n realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]);\ \n }\ \n _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs;\ \n _nrb->_weight_index[_nrb->_cnt] = _weight_index;\ \n _nrb->_nrb_t[_nrb->_cnt] = _nt->_t;\ \n _nrb->_nrb_flag[_nrb->_cnt] = _lflag;\ \n ++_nrb->_cnt;\ \n}\ \n"); insertstr(q, buf); sprintf(buf, "\ \nstatic void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag)\ \n#else\ \n"); insertstr(q, buf); /* close off */ q = net_receive_block_open_brace_; insertstr(q, "\n#endif\n"); } static void emit_nrn_watch_check_code() { Item* q, *par1, *par2, *flag; int iw; char* par2par; Lappendstr(procfunc, "\n" "void _nrn_watch_check(NrnThread* _nt, Memb_list* _ml) {\n" " double* _p; Datum* _ppvar; ThreadDatum* _thread;\n" " int* _ni; double v; int _iml, _cntml_padded, _cntml_actual;\n" " _cntml_actual = _ml->_nodecount;\n" " _cntml_padded = _ml->_nodecount_padded;\n" " _ni = _ml->_nodeindices;\n" " _thread = _ml->_thread;\n" " double * _nt_data = _nt->_data;\n" " double * _vec_v = _nt->_actual_v;\n" " int stream_id = _nt->stream_id;\n" ); /* for gpu, performance may be better factored into below ITERATE */ Lappendstr(procfunc, "\n" " #if LAYOUT == 1 /*AoS*/\n" " for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n" " _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize;\n" " #elif LAYOUT == 0 /*SoA*/\n" " _p = _ml->_data; _ppvar = _ml->_pdata;\n" " /* insert compiler dependent ivdep like pragma */\n" " _PRAGMA_FOR_VECTOR_LOOP_\n" " _PRAGMA_FOR_STATE_ACC_LOOP_\n" " for (_iml = 0; _iml < _cntml_actual; ++_iml) {\n" " #else /* LAYOUT > 1 */ /*AoSoA*/\n" " #error AoSoA not implemented.\n" " for (;;) { /* help clang-format properly indent */\n" " #endif\n" " v = _vec_v[_ni[_iml]];\n" "#if NRN_PRCELLSTATE\n" " _v_unused = v;\n" "#endif\n" " bool _untriggered = true;\n" ); iw = 0; /* 0 unused Datum but for consistent size with NEURON... */ ITERATE(q, watch_data_) { /* triples of par1, par2, flag items */ par1 = ITM(q); q = q->next; par2 = ITM(q); q = q->next; flag = ITM(q); ++iw; par2par = items_as_string(par1, par2); sprintf(buf, "\n" " if (_watch_array(%d)&2 && _untriggered) {\n" " if %s {\n" " if ((_watch_array(%d)&1) == 0) {\n" " _untriggered = false;\n" " #if NET_RECEIVE_BUFFERING\n" " _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, -1, _ppvar[1*_STRIDE], t + 0.0 , %s );\n" " #else\n" " net_send ( _tqitem, -1, (Point_process*) _nt->_vdata[_ppvar[1*_STRIDE]], t + 0.0 , %s ) ;\n" " #endif\n" " }\n" " _watch_array(%d) = 3;\n" " }else{\n" " _watch_array(%d) = 2;\n" " }\n" " }\n" , iw, par2par, iw, STR(flag), STR(flag), iw, iw); Lappendstr(procfunc, buf); free(par2par); } sprintf(buf, " }\n"); Lappendstr(procfunc, buf); Lappendstr(procfunc, "\n" "#if NET_RECEIVE_BUFFERING\n" " NetSendBuffer_t* _nsb = _ml->_net_send_buffer;\n" "#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\n" " #pragma acc wait(stream_id)\n" " #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu)\n" " update_net_send_buffer_on_host(_nt, _nsb);\n" "#endif\n" " {int _i;\n" " for (_i=0; _i < _nsb->_cnt; ++_i) {\n" " net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i],\n" " _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i],\n" " _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]);\n" " }}\n" " _nsb->_cnt = 0;\n" "#if defined(_OPENACC) && !defined(DISABLE_OPENACC)\n" " #pragma acc update device(_nsb->_cnt) if(_nt->compute_gpu)\n" "#endif\n" "#endif\n" ); Lappendstr(procfunc, "}\n"); } void net_receive(qblk, qarg, qp1, qp2, qstmt, qend) Item* qblk, *qarg, *qp1, *qp2, *qstmt, *qend; { Item* q, *q1; Symbol* s; int i, b; char snew[100]; if (net_receive_) { diag("Only one NET_RECEIVE block allowed", (char*)0); } if (!point_process) { diag("NET_RECEIVE can only exist in a POINT_PROCESS", (char*)0); } net_receive_ = 1; net_receive_block_begin_ = qblk; deltokens(qp1, qp2); insertstr(qstmt, "(Point_process* _pnt, int _weight_index, double _lflag)"); i = 0; ITERATE(q1, qarg) if (q1->next != qarg) { /* skip last "flag" arg */ s = SYM(q1); sprintf(snew, "_args[%d]", i); ++i; for (q = qstmt; q != qend; q = q->next) { if (q->itemtype == SYMBOL && SYM(q) == s) { replacstr(q, snew); } } } net_send_delivered_ = qstmt; q = insertstr(qstmt, "\n{"); net_receive_block_open_brace_ = q; vectorize_substitute(q, "\n\ { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0;\n\ Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args;\n\ "); if (watch_seen_) { insertstr(qstmt, " int _watch_rm = 0;\n"); } q = insertstr(qstmt, net_boilerplate(1)); if (debugging_) { if (1) { insertstr(qstmt, " #if !defined(_OPENACC) \n assert(_tsav <= t); \n #endif \n _tsav = t;"); }else{ insertstr(qstmt, " if (_tsav > t){ extern char* hoc_object_name(); hoc_execerror(hoc_object_name(_pnt->ob), \":Event arrived out of order. Must call ParallelContext.set_maxstep AFTER assigning minimum NetCon.delay\");}\n _tsav = t;"); } } insertstr(qend, "}"); insertstr(qend, "\ \n#if NET_RECEIVE_BUFFERING\ \n#undef t\ \n#define t _nt->_t\ \n#endif\ \n"); if (!artificial_cell) { Symbol* ions[10]; int j, nion=0; /* v can be changed in the NET_RECEIVE block since it is called between integrator steps and before a re_init but no need to do so if it is not used. Note the subtle problem that results from not mentioning v in the NET_RECEIVE block but calling a function that uses it. That is highly unlikely to occur but should we insert the statements no matter what? Rather than that it would probably be better to revert to standard mod2c (nocmodl) _threadargs_ style that requires an explicit v arg by the user to a function. */ Symbol* vsym = lookup("v"); for (q = qstmt; q != qend; q = q->next) { if (q->itemtype == SYMBOL && SYM(q) == vsym) { insertstr(qstmt, " v = VEC_V(_ml->_nodeindices[_iml]);\n"); insertstr(qend, "\n VEC_V(_ml->_nodeindices[_iml]) = v;\n"); break; } } /* if an ion concentration is mentioned then we need to get the relevant value on entry and possibly set a value on exit Do not allow mention of reversal potential or current */ for (q = qstmt; q != qend; q = q->next) { if (q->itemtype == SYMBOL && SYM(q)->type == NAME) { s = SYM(q); if ((s->nrntype & (NRNPRANGEIN | NRNPRANGEOUT)) == 0) { continue; } if ((s->nrntype & IONCONC) == 0) { diag(s->name, " :only concentrations can be mentioned in a NET_RECEIVE block"); } /* distinct only */ for (j=0; j < nion; ++j) { if (s == ions[j]) { break; } } if (j == nion) { if (nion >= 10) { diag("too many ions mentioned in NET_RECEIVE block (limit 10", (char*)0); } ions[nion] = s; ++nion; } } } for (j = 0; j < nion; ++j) { sprintf(buf, "%s %s = _ion_%s;\n", (j==0)?"\n":"", ions[j]->name, ions[j]->name); insertstr(qstmt, buf); } for (j = 0; j < nion; ++j) { if (ions[j]->subtype & STAT) { sprintf(buf, "%s _ion_%s = %s;\n", (j==0)?"\n":"", ions[j]->name, ions[j]->name); insertstr(qend, buf); } } } if (i > 0) { net_receive_ = i; } if (net_init_q1_) { movelist(net_init_q1_, net_init_q2_, procfunc); } } void net_init(qinit, qp2) Item* qinit, *qp2; { Item* q_before_boilerplate; Item* q_after_boilerplate; /* qinit=INITIAL { stmtlist qp2=} */ replacstr(qinit, "\nvoid _net_init(Point_process* _pnt, int _weight_index, double _lflag)"); vectorize_substitute(insertstr(qinit->next->next, ""), "\n\ double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0;\n\ Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args;\n\ "); q_after_boilerplate = insertstr(qinit->next->next->next, ""); q_before_boilerplate = insertstr(q_after_boilerplate, ""); vectorize_substitute(insertstr(q_before_boilerplate, ""), net_boilerplate(0)); if (net_init_q1_) { diag("NET_RECEIVE block can contain only one INITIAL block", (char*)0); } if (!artificial_cell) { /* Do not expect to use v, but all function calls need it due to _threadargs_. Can use the value of v but changing v will not take effect on return */ insertstr(q_after_boilerplate, " v = VEC_V(_ml->_nodeindices[_iml]);\n"); } net_init_q1_ = qinit; net_init_q2_ = qp2; } void fornetcon(keyword, par1, args, par2, stmt, qend) Item* keyword, *par1, *args, *par2, *stmt, *qend; { Item* q, *q1; Symbol* s; char snew[100]; int i; /* follows net_receive pretty closely */ ++for_netcons_; deltokens(par1, par2); sprintf(buf, "\t{size_t _ix, _ifn, _ifn_begin, _ifn_end; double* _fnargs%d;\n" "\t _ix = size_t(_ppvar[_fnc_index*_STRIDE]);\n" "\t _ifn_begin = _nt->_fornetcon_perm_indices[_ix];\n" "\t _ifn_end = _nt->_fornetcon_perm_indices[_ix + 1];\n" "\t size_t* _fnargs_order{_nt->_fornetcon_weight_perm};\n" "\t for (_ifn = _ifn_begin; _ifn < _ifn_end; ++_ifn) {\n" "\t _fnargs%d = _weights + _fnargs_order[_ifn];\n", for_netcons_, for_netcons_); replacstr(keyword, buf); insertstr(qend->next, "\t}}\n"); i = 0; ITERATE(q1, args) { s = SYM(q1); sprintf(snew, "_fnargs%d[%d]", for_netcons_, i); ++i; for (q = stmt; q != qend; q = q->next) { if (q->itemtype == SYMBOL && SYM(q) == s) { replacstr(q, snew); } } } } void chk_thread_safe() { Symbol* s; int i; Item* q; SYMLISTITER { /* globals are now global with respect to C as well as hoc */ s = SYM(q); if (s->nrntype & (NRNGLOBAL) && s->assigned_to_ == 1) { sprintf(buf, "Assignment to the GLOBAL variable, \"%s\", is not thread safe", s->name); threadsafe(buf); } } } void threadsafe_seen(Item* q1, Item* q2) { Item* q; assert_threadsafe = 1; if (q2) { for (q = q1->next; q != q2->next; q = q->next) { SYM(q)->assigned_to_ = 2; } } } void conductance_hint(int blocktype, Item* q1, Item* q2) { Item* q; if (blocktype != BREAKPOINT) { diag("CONDUCTANCE can only appear in BREAKPOINT block", (char*)0); } if (!conductance_) { conductance_ = newlist(); } lappendsym(conductance_, SYM(q1->next)); if (q2 != q1->next) { Symbol* s = SYM(q2); if (!ion_declared(s)) { diag(s->name, " not declared as USEION in NEURON block"); } lappendsym(conductance_, s); }else{ lappendsym(conductance_, SYM0); } deltokens(q1, q2); } void possible_local_current(int blocktype, List* symlist) { Item* q; Item* q2; if (blocktype != BREAKPOINT) { return; } ITERATE(q, currents) { ITERATE(q2, symlist) { char* n = SYM(q2)->name + 2; /* start after the _l */ if (strcmp(SYM(q)->name, n) == 0) { if (!breakpoint_local_current_) { breakpoint_local_current_ = newlist(); } lappendsym(breakpoint_local_current_, SYM(q)); lappendsym(breakpoint_local_current_, SYM(q2)); } } } } Symbol* breakpoint_current(Symbol* s) { if (breakpoint_local_current_) { Item* q; ITERATE(q, breakpoint_local_current_) { if (SYM(q) == s) { return SYM(q->next); } } } return s; } /* writes item as string to cp and returns end of string */ /* cp must be big enough */ char* item2str(Item* q, char* cp) { if (q->itemtype == SYMBOL) { sprintf(cp, " %s", SYM(q)->name); } else if (q->itemtype == VERBATIM) { sprintf(cp, "%s", STR(q)); } else if (q->itemtype == ITEM) { item2str(ITM(q), cp); }else { sprintf(cp, " %s", STR(q)); } return cp + strlen(cp); } char* items_as_string(Item* q1, Item* q2) { Item* q; char s[8192]; char* cp = s; *cp = '\0'; for (q = q1; q != q2->next; q = q->next) { cp = item2str(q, cp); } return strdup(s); } mod2c-8.2.2/src/mod2c_core/parsact.c000066400000000000000000001106041425457616700171560ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* * some parse actions to reduce size of parse.y the installation routines can * also be used, e.g. in sens to automattically construct variables */ #include #include "modl.h" #include "parse1.h" Symbol *scop_indep; /* independent used by SCoP */ Symbol *indepsym; /* only one independent variable */ Symbol *stepsym; /* one or fewer stepped variables */ List *indeplist; /* FROM TO WITH START UNITS */ extern List *syminorder; /* Order in which variables are output to * .var file */ #if CVODE extern List* state_discon_list_; extern int net_send_seen_; extern int net_event_seen_; extern int watch_seen_; extern List* watch_data_; #endif int protect_; int protect_include_; int net_send_buffer_in_initial; extern Item* vectorize_replacement_item(Item*); extern int artificial_cell; extern int vectorize; extern int assert_threadsafe; static int type_change(Symbol*, int); static long previous_subtype; /* subtype at the sym->level */ static char *previous_str; /* u.str on last install */ void explicit_decl(int level, Item* q) { /* used to be inside parse1.y without the lastvars condition Without the condition it served two purposes. 1) variables explicitly declared were so marked so that they would appear first in the .var file. Unmarked variables appear last. 2) Give error message if a variable was explicitly declared more than once. Now, the merge program produces declaration blocks from submodels with a prepended LAST_VARS keyword. This implies 1) that variables in such blocks should appear last (if they don't appear at the top level) and 2) multiple declarations are not errors. Hence we merely enclose the old code in an if statement The question arises, on multiple declarations, which value does the .var file get. In the current implementation it is the last one seen. If this is not right (and a better method would be keep the value declared closest to the root) then it will be the responsibility of merge to delete multiple declarations. */ /* Solving the multiple declaration problem. merge now gives the level number of the declaration with the root file having level number 0, all its submodels having level number 1, submodels of level 1 submodels having level 2, etc. The rule is that the lowest level declaration is used. If two declarations exist at the same level then it is an error unless their u.str are identical. Since, by the time this routine is called the latest declaration has already been installed, each installation routine saves the previous u.str in a static variable. Also a new field is added to the symbol structure to keep track of its level. At this time we retain the EXPLICIT_DECL field for explicit declarations at the root level. The default level when the symbol is allocated is 100. */ Symbol *sym; sym = SYM(q); if (!level) { /* No multiple declarations at the root level and the symbol is marked explicitly declared */ if (sym->usage & EXPLICIT_DECL) { diag("Multiple declaration of ", sym->name); } sym->usage |= EXPLICIT_DECL; } /* this ensures that declared PRIMES will appear in .var file */ sym->usage |= DEP; if (level >= sym->level) { assert(previous_str); } /* resolve possible type conflicts */ if (type_change(sym, level)) { return; } /* resolve which declaration takes precedence */ if (level < sym->level) { /* new one takes precedence */ sym->level = level; }else if (level > sym->level) { /* old one takes precedence */ sym->u.str = previous_str; }else if (strcmp(sym->u.str, previous_str) != 0) { /* not identical */ diag(sym->name, " has different values at same level"); } } /* restricted type changes are allowed in hierarchical models with each one producing a message. Notice that multiple declarations at level 0 are caught as errors in the function above. */ static int type_change(Symbol* sym, int level) /*return 1 if type change, 0 otherwise*/ { long s, d, c; s = sym->subtype & STAT; d = sym->subtype & DEP; c = sym->subtype & PARM; if (s && c) { sym->subtype &= ~c; Fprintf(stderr, "Notice: %s is promoted from a PARAMETER to a STATE\n", sym->name); if (previous_subtype & STAT) { sym->u.str = previous_str; } }else if (s && d) { sym->subtype &= ~d; Fprintf(stderr, "WARNING: %s is promoted from an ASSIGNED to a STATE\n", sym->name); if (previous_subtype & STAT) { sym->u.str = previous_str; } }else if (d && c) { sym->subtype &= ~c; Fprintf(stderr, "Notice: %s is promoted from a PARAMETER to an ASSIGNED\n", sym->name); if (previous_subtype & DEP) { sym->u.str = previous_str; } }else{ return 0; } if (level < sym->level) { sym->level = level; } return 1; } void parm_array_install(Symbol* n, char* num, char* units, char* limits, int index) { char buf[NRN_BUFSIZE]; previous_subtype = n->subtype; previous_str = n->u.str; if (n->u.str == (char *) 0) Lappendsym(syminorder, n); n->subtype |= PARM; n->subtype |= ARRAY; n->araydim = index; Sprintf(buf, "[%d]\n%s\n%s\n%s\n", index, num, units, limits); n->u.str = stralloc(buf, (char *) 0); } void parminstall(n, num, units, limits) Symbol *n; char *num, *units, *limits; { char buf[NRN_BUFSIZE]; previous_subtype = n->subtype; previous_str = n->u.str; if (n->u.str == (char *) 0) Lappendsym(syminorder, n); n->subtype |= PARM; Sprintf(buf, "\n%s\n%s\n%s\n", num, units, limits); n->u.str = stralloc(buf, (char *) 0); } /* often we want to install a parameter by default but only if the user hasn't declared it herself. */ Symbol *ifnew_parminstall(name, num, units, limits) char *name, *num, *units, *limits; { Symbol *s; if ((s = lookup(name)) == SYM0) { s = install(name, NAME); parminstall(s, num, units, limits); } if (!(s->subtype)) { /* can happen when PRIME used in MATCH */ parminstall(s, num, units, limits); } if (!(s->subtype & (PARM | STEP1))) { /* special case is scop_indep can be a PARM but not indepsym */ if (scop_indep == indepsym || s != scop_indep) { diag(s->name, " can't be declared a parameter by default"); } } return s; } void steppedinstall(n, q1, q2, units) Symbol *n; Item *q1, *q2; char *units; { int i; char buf[NRN_BUFSIZE]; static int seestep = 0; previous_subtype = n->subtype; previous_str = n->u.str; if (seestep) { diag("Only one STEPPED variable can be defined", (char *) 0); } seestep = 1; stepsym = n; i = 0; Strcpy(buf, "\n"); Strcat(buf, STR(q1)); while (q1 != q2) { q1 = q1->next; Strcat(buf, SYM(q1)->name); /* , is a symbol */ q1 = q1->next; Strcat(buf, STR(q1)); i++; if (i > 5) { diag("Maximum of 5 steps in a stepped variable", (char *) 0); } } Strcat(buf, "\n"); Strcat(buf, units); Strcat(buf, "\n"); n->subtype |= STEP1; n->u.str = stralloc(buf, (char *) 0); } static char *indepunits = ""; #if NMODL int using_default_indep; #endif void indepinstall(n, from, to, with, qstart, units, scop) Symbol *n; char *from, *to, *with, *units; Item *qstart; /* ITEM0 if not present */ int scop; /*1 if declaring the scop independent*/ { char buf[NRN_BUFSIZE]; /* scop_indep may turn out to be different from indepsym. If this is the case then indepsym will be a constant in the .var file (see parout.c). If they are the same, then u.str gets the info from SCOP. */ if (!scop) { #if NMODL if (using_default_indep) { using_default_indep = 0; if (indepsym != n) { indepsym->subtype &= ~INDEP; parminstall(indepsym, "0", "ms", ""); } indepsym = (Symbol*)0; } #endif if (indepsym) { diag("Only one independent variable can be defined", (char *) 0); } indeplist = newlist(); Lappendstr(indeplist, from); Lappendstr(indeplist, to); Lappendstr(indeplist, with); if (qstart) { Lappendstr(indeplist, STR(qstart)); }else{ Lappendstr(indeplist, from); } Lappendstr(indeplist, units); n->subtype |= INDEP; indepunits = stralloc(units, (char *) 0); if (n != scop_indep) { Sprintf(buf, "\n%s*%s(%s)\n%s\n", from, to, with, units); n->u.str = stralloc(buf, (char *) 0); } indepsym = n; if (!scop_indep) { scop_indep = indepsym; } }else{ n->subtype |= INDEP; Sprintf(buf, "\n%s*%s(%s)\n%s\n", from, to, with, units); n->u.str = stralloc(buf, (char *) 0); scop_indep = n; } } /* * installation of dependent and state variables type 0 -- dependent; 1 -- * state index 0 -- scalar; otherwise -- array qs -- item pointer to START * const string makeconst 0 -- do not make a default constant for state 1 -- * make sure name0 exists For states Dname and name0 are normally created. * However Dname will not appear in the .var file unless it is used -- see * parout.c. */ void depinstall(type, n, index, from, to, units, qs, makeconst, abstol) int type, index, makeconst; Symbol *n; char *from, *to, *units, *abstol; Item *qs; { char buf[NRN_BUFSIZE], *pstr; int c; if (!type && strlen(abstol)>0) { printf("abstol = |%s|\n", abstol); diag(n, "tolerance can be specified only for a STATE"); } pstr = n->u.str; /* make it work even if recursive */ if (n->u.str == (char *) 0) Lappendsym(syminorder, n); if (type) { n->subtype |= STAT; c = ':'; statdefault(n, index, units, qs, makeconst); } else { n->subtype |= DEP; c = ';'; if (qs) { diag("START not legal except in STATE block", (char *) 0); } } if (index) { Sprintf(buf, "[%d]\n%s%c%s\n%s\n%s\n", index, from, c, to, units, abstol); n->araydim = index; n->subtype |= ARRAY; } else { Sprintf(buf, "\n%s%c%s\n%s\n%s\n", from, c, to, units, abstol); } n->u.str = stralloc(buf, (char *) 0); previous_subtype = n->subtype; previous_str = pstr; } void statdefault(n, index, units, qs, makeconst) Symbol *n; int index, makeconst; char *units; Item *qs; { char nam[30], *un; Symbol *s; if (n->type != NAME && n->type != PRIME) { diag(n->name, " can't be a STATE"); } if (makeconst) { Sprintf(nam, "%s0", n->name); s = ifnew_parminstall(nam, "0", units, ""); if (qs) { /*replace with proper default*/ parminstall(s, STR(qs), units, ""); } } Sprintf(nam, "%s/%s", units, indepunits); un = stralloc(nam, (char *) 0); Sprintf(nam, "D%s", n->name); if ((s = lookup(nam)) == SYM0) { /* install the prime as a DEP */ s = install(nam, PRIME); depinstall(0, s, index, "0", "1", un, ITEM0, 0, ""); } } /* the problem is that qpar->next may already have a _p, ..., _nt vectorize_substitute, and qpar->next is often normally "" instead of ')' for the no arg case. */ static int func_arg_examine(Item* qpar, Item* qend) { Item* q; int b = 1; /* real args exist case */ q = qpar->next; if (q->itemtype == SYMBOL && strcmp(SYM(q)->name, ")") == 0) { b = 0; /* definitely no arg */ } if (q->itemtype == STRING && strcmp(STR(q), "") == 0) { if (vectorize_replacement_item(q)) { b = 2; /* _p,..._nt already there */ } else if (q->next->itemtype == SYMBOL && strcmp(SYM(q->next)->name, ")") == 0) { b = 0; /* definitely no arg */ } } return b; } void vectorize_scan_for_func(Item* q1, Item* q2) { Item* q, *qq; int b; return; for (q = q1; q != q2; q = q->next) { if (q->itemtype == SYMBOL) { Symbol* s = SYM(q); if ((s->usage & FUNCT) && !(s->subtype & (EXTDEF))) { if (q->next->itemtype == SYMBOL && strcmp(SYM(q->next)->name, "(") == 0) { int b = func_arg_examine(q->next, q2); if (b == 0) { /* no args */ vectorize_substitute(q->next, "(_threadargs_"); }else if (b == 1) { /* real args */ vectorize_substitute(q->next, "(_threadargs_,"); } /* else no _p.._nt already there */ } } } } } void defarg(q1, q2) /* copy arg list and define as doubles */ Item *q1, *q2; { Item *q3, *q; if (q1->next == q2) { #if VECTORIZE vectorize_substitute(insertstr(q2, ""), "_threadargsproto_"); #endif return; } for (q = q1->next; q != q2; q = q->next) { if (strcmp(SYM(q)->name, ",") != 0) { insertstr(q, "double"); } } #if VECTORIZE vectorize_substitute(insertstr(q1->next, ""), "_threadargsprotocomma_"); #endif } void lag_stmt(q1, blocktype) /* LAG name1 BY name2 */ Item *q1; int blocktype; { Symbol *name1, *name2, *lagval; /*ARGSUSED*/ /* parse */ name1 = SYM(q1->next); delete(q1->next); delete(q1->next); name2 = SYM(q1->next); delete(q1->next); name1->usage |= DEP; name2->usage |= DEP; /* check */ if (!indepsym) { diag("INDEPENDENT variable must be declared to process", " the LAG statement"); } if (!(name1->subtype & (DEP | STAT))) { diag(name1->name, " not a STATE or DEPENDENT variable"); } if (!(name2->subtype & (PARM | nmodlCONST))) { diag(name2->name, " not a CONSTANT or PARAMETER"); } Sprintf(buf, "lag_%s_%s", name1->name, name2->name); if (lookup(buf)) { diag(buf, " already in use"); } /* create */ lagval = install(buf, NAME); lagval->usage |= DEP; lagval->subtype |= DEP; if (name1->subtype & ARRAY) { lagval->subtype |= ARRAY; lagval->araydim = name1->araydim; } if (lagval->subtype & ARRAY) { Sprintf(buf, "static double *%s;\n", lagval->name); Linsertstr(procfunc, buf); Sprintf(buf, "%s = lag(%s, %s, %s, %d);\n", lagval->name, name1->name, indepsym->name, name2->name, lagval->araydim); }else{ Sprintf(buf, "static double %s;\n", lagval->name); Linsertstr(procfunc, buf); Sprintf(buf, "%s = *lag(&(%s), %s, %s, 0);\n", lagval->name, name1->name, indepsym->name, name2->name); } replacstr(q1, buf); } void queue_stmt(q1, q2) Item *q1, *q2; { Symbol *s; static int first=1; if (first) { first = 0; Linsertstr(initfunc, "initqueue();\n"); } if (SYM(q1)->type == PUTQ) { replacstr(q1, "enqueue("); }else{ replacstr(q1, "dequeue("); } s = SYM(q2); s->usage |= DEP; if (!(s->subtype)) { diag(s->name, " not declared"); } if (s->subtype & ARRAY) { Sprintf(buf, "%s, %d);\n", s->name, s->araydim); }else{ Sprintf(buf, "&(%s), 1);\n", s->name); } replacstr(q2, buf); } void add_reset_args(q) Item *q; { static int reset_fun_cnt=0; reset_fun_cnt++; Sprintf(buf, "&_reset, &_freset%d,", reset_fun_cnt); Insertstr(q->next, buf); Sprintf(buf, "static double _freset%d;\n", reset_fun_cnt); Lappendstr(firstlist, buf); } void add_nrnthread_arg(q) Item *q; { vectorize_substitute(insertstr(q->next, "nrn_threads,"), "_nt,"); } /* table manipulation */ /* arglist must have exactly one argument tablist contains 1) list of names to be looked up (must be empty if qtype is FUNCTION and nonempty if qtype is PROCEDURE). 2) From expression list 3) To expression list 4) With integer string 5) DEPEND list as list of names The qname does not have a _l if a function. The arg names all have _l prefixes. */ /* checking and creation of table has been moved to separate function called static _check_func. */ /* to allow vectorization the table functions are separated into name robust function. makes sure table is uptodate (calls check_name) _check_name if table not up to date then builds table _f_name analytic _n_name table lookup with no checking if usetable=1 otherwise calls _f_name. */ static List* check_table_statements; static Symbol* last_func_using_table; void check_tables() { /* for threads do this differently */ if (check_table_statements) { fprintf(fcout, "\n#if %d\n", 0); printlist(check_table_statements); fprintf(fcout, "#endif\n"); } } /* this way we can make sure the tables are up to date in the main thread at critical points in the finitialize, nrn_fixed_step, etc. The only requirement is that the function that generates the table not use any except GLOBAL parameters and assigned vars not requiring an initial value, because we are probably going to call this with nonsense _p, _ppvar, and _thread */ static List* check_table_thread_list; int check_tables_threads(List* p) { Item* q; if (check_table_thread_list) { ITERATE(q, check_table_thread_list) { sprintf(buf, "\nstatic void %s(_threadargsproto_);", STR(q)); lappendstr(p, buf); } lappendstr(p, "\nstatic void _check_table_thread(int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, int v) {\n"); ITERATE(q, check_table_thread_list) { sprintf(buf, " %s(_threadargs_);\n", STR(q)); lappendstr(p, buf); } lappendstr(p, "}\n"); return 1; } return 0; } void table_massage(tablist, qtype, qname, arglist) List *tablist, *arglist; Item *qtype, *qname; { Symbol *fsym, *s, *arg=0; char* fname; List *table, *from, *to, *depend; int type, ntab; Item *q; if (!tablist) { return; } fsym = SYM(qname); last_func_using_table = fsym; fname = fsym->name; table = LST(q = tablist->next); from = LST(q = q->next); to = LST(q = q->next); ntab = atoi(STR(q = q->next)); depend = LST(q = q->next); type = SYM(qtype)->type; ifnew_parminstall("usetable", "1", "", "0 1"); if (!check_table_statements) { check_table_statements = newlist(); } sprintf(buf, "_check_%s();\n", fname); q = lappendstr(check_table_statements, buf); sprintf(buf, "_check_%s(_threadargs_);\n", fname); vectorize_substitute(q, buf); /*checking*/ if (type == FUNCTION1) { if (table) { diag("TABLE stmt in FUNCTION cannot have a table name list", (char *)0); } table = newlist(); Lappendsym(table, fsym); }else{ if (!table) { diag("TABLE stmt in PROCEDURE must have a table name list", (char *)0); } } if (arglist->next == arglist || arglist->next->next != arglist) { diag("FUNCTION or PROCEDURE containing a TABLE stmt\n", "must have exactly one argument"); }else{ arg = SYM(arglist->next); } if (!depend) { depend = newlist(); } /*translation*/ /* new name for original function */ Sprintf(buf, "_f_%s", fname); SYM(qname) = install(buf, fsym->type); SYM(qname)->subtype = fsym->subtype; SYM(qname)->varnum = fsym->varnum; if (type == FUNCTION1) { fsym->subtype |= FUNCT; Sprintf(buf, "static double _n_%s(double);\n", fname); q = linsertstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "static double _n_%s(_threadargsprotocomma_ double _lv);\n", fname); vectorize_substitute(q, buf); #endif }else{ fsym->subtype |= PROCED; Sprintf(buf, "static void _n_%s(double);\n", fname); q = linsertstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "static void _n_%s(_threadargsprotocomma_ double _lv);\n", fname); vectorize_substitute(q, buf); #endif } fsym->usage |= FUNCT; /* declare communication between func and check_func */ Sprintf(buf, "static double _mfac_%s, _tmin_%s;\n", fname, fname); Lappendstr(procfunc, buf); /* create the check function */ if (!check_table_thread_list) { check_table_thread_list = newlist(); } sprintf(buf, "_check_%s", fname); lappendstr(check_table_thread_list, buf); Sprintf(buf, "static void _check_%s();\n", fname); q = insertstr(procfunc, buf); vectorize_substitute(q, ""); Sprintf(buf, "static void _check_%s() {\n", fname); q = lappendstr(procfunc, buf); Sprintf(buf, "static void _check_%s(_threadargsproto_) {\n", fname); vectorize_substitute(q, buf); Lappendstr(procfunc, " static int _maktable=1; int _i, _j, _ix = 0;\n"); Lappendstr(procfunc, " double _xi, _tmax;\n"); ITERATE(q, depend) { Sprintf(buf, " static double _sav_%s;\n", SYM(q)->name); Lappendstr(procfunc, buf); } lappendstr(procfunc, " if (!usetable) {return;}\n"); /*allocation*/ ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, " for (_i=0; _i < %d; _i++) {\ _t_%s[_i] = makevector(%d*sizeof(double)); }\n", s->araydim, s->name, ntab+1); }else{ Sprintf(buf, " _t_%s = makevector(%d*sizeof(double));\n", s->name, ntab+1); } Lappendstr(initlist, buf); } /* check dependency */ ITERATE(q, depend) { Sprintf(buf, " if (_sav_%s != %s) { _maktable = 1;}\n", SYM(q)->name, SYM(q)->name); Lappendstr(procfunc, buf); } /* make the table */ Lappendstr(procfunc, " if (_maktable) { double _x, _dx; _maktable=0;\n"); Sprintf(buf, " _tmin_%s = ", fname); Lappendstr(procfunc, buf); move(from->next, from->prev, procfunc); Sprintf(buf, ";\n _tmax = "); Lappendstr(procfunc, buf); move(to->next, to->prev, procfunc); Lappendstr(procfunc, ";\n"); Sprintf(buf," _dx = (_tmax - _tmin_%s)/%d.; _mfac_%s = 1./_dx;\n", fname, ntab, fname); Lappendstr(procfunc, buf); Sprintf(buf," for (_i=0, _x=_tmin_%s; _i < %d; _x += _dx, _i++) {\n", fname, ntab+1); Lappendstr(procfunc, buf); if (type == FUNCTION1) { ITERATE(q, table) { s = SYM(q); Sprintf(buf, " _t_%s[_i] = _f_%s(_x);\n", s->name, fname); Lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, " _t_%s[_i] = _f_%s(_threadargs_, _x);\n", s->name, fname); vectorize_substitute(procfunc->prev, buf); #endif } }else{ Sprintf(buf, " _f_%s(_x);\n", fname); Lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, " _f_%s(_threadargs_, _x);\n", fname); vectorize_substitute(procfunc->prev, buf); #endif ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, " for (_j = 0; _j < %d; _j++) { _t_%s[_j][_i] = %s[_j];\n}", s->araydim, s->name, s->name); }else{ Sprintf(buf, " _t_%s[_i] = %s;\n", s->name, s->name); } Lappendstr(procfunc, buf); } } Lappendstr(procfunc, " }\n"); /*closes loop over _i index*/ /* save old dependency values */ ITERATE(q, depend) { s = SYM(q); Sprintf(buf, " _sav_%s = %s;\n", s->name, s->name); Lappendstr(procfunc, buf); } Lappendstr(procfunc, " }\n"); /* closes if(maktable)) */ Lappendstr(procfunc, "}\n\n"); /* create the new function (steers to analytic or table) */ /*declaration*/ if (type == FUNCTION1) { #define GLOBFUNC 1 #if !GLOBFUNC Lappendstr(procfunc, "static int"); #endif Lappendstr(procfunc, "double"); }else{ Lappendstr(procfunc, "static int"); } Sprintf(buf, "%s(double %s){", fname, arg->name); Lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "%s(_threadargsproto_, double %s) {", fname, arg->name); vectorize_substitute(procfunc->prev, buf); #endif /* check the table */ Sprintf(buf, "_check_%s();\n", fname); q = lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "\n#if 0\n_check_%s(_threadargs_);\n#endif\n", fname); vectorize_substitute(q, buf); #endif if (type == FUNCTION1) { Lappendstr(procfunc, "return"); } Sprintf(buf, "_n_%s(%s);\n", fname, arg->name); Lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "_n_%s(_threadargs_, %s);\n", fname, arg->name); vectorize_substitute(procfunc->prev, buf); #endif if (type != FUNCTION1) { Lappendstr(procfunc, "return 0;\n"); } Lappendstr(procfunc, "}\n\n"); /* end of new function */ /* _n_name function for table lookup with no checking */ if (type == FUNCTION1) { Lappendstr(procfunc, "static double"); }else{ Lappendstr(procfunc, "static void"); } Sprintf(buf, "_n_%s(double %s){", fname, arg->name); Lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "_n_%s(_threadargsproto_, double %s){", fname, arg->name); vectorize_substitute(procfunc->prev, buf); #endif Lappendstr(procfunc, "int _i, _j;\n"); Lappendstr(procfunc, "double _xi, _theta;\n"); /* usetable */ Lappendstr(procfunc, "if (!usetable) {\n"); if (type == FUNCTION1) { Lappendstr(procfunc, "return"); } Sprintf(buf, "_f_%s(%s);", fname, arg->name); Lappendstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "_f_%s(_threadargs_, %s);", fname, arg->name); vectorize_substitute(procfunc->prev, buf); #endif if (type != FUNCTION1) { Lappendstr(procfunc, "return;"); } Lappendstr(procfunc, "\n}\n"); /* table lookup */ Sprintf(buf, "_xi = _mfac_%s * (%s - _tmin_%s);\n", fname, arg->name, fname); Lappendstr(procfunc, buf); Lappendstr(procfunc, "if (isnan(_xi)) {\n"); if (type == FUNCTION1) { Lappendstr(procfunc, " return _xi; }\n"); }else{ ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, " for (_j = 0; _j < %d; _j++) { %s[_j] = _xi;\n}", s->araydim, s->name); }else{ Sprintf(buf, " %s = _xi;\n", s->name); } Lappendstr(procfunc, buf); } Lappendstr(procfunc, " return;\n }\n"); } Lappendstr(procfunc, "if (_xi <= 0.) {\n"); if (type == FUNCTION1) { Sprintf(buf, "return _t_%s[0];\n", SYM(table->next)->name); Lappendstr(procfunc, buf); }else{ ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "for (_j = 0; _j < %d; _j++) { %s[_j] = _t_%s[_j][0];\n}", s->araydim, s->name, s->name); }else{ Sprintf(buf, "%s = _t_%s[0];\n", s->name, s->name); } Lappendstr(procfunc, buf); } Lappendstr(procfunc, "return;"); } Lappendstr(procfunc, "}\n"); Sprintf(buf, "if (_xi >= %d.) {\n", ntab); Lappendstr(procfunc, buf); if (type == FUNCTION1) { Sprintf(buf, "return _t_%s[%d];\n", SYM(table->next)->name, ntab); Lappendstr(procfunc, buf); }else{ ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "for (_j = 0; _j < %d; _j++) { %s[_j] = _t_%s[_j][%d];\n}", s->araydim, s->name, s->name, ntab); }else{ Sprintf(buf, "%s = _t_%s[%d];\n", s->name, s->name, ntab); } Lappendstr(procfunc, buf); } Lappendstr(procfunc, "return;"); } Lappendstr(procfunc, "}\n"); /* table interpolation */ Lappendstr(procfunc, "_i = (int) _xi;\n"); if (type == FUNCTION1) { s = SYM(table->next); Sprintf(buf, "return _t_%s[_i] + (_xi - (double)_i)*(_t_%s[_i+1] - _t_%s[_i]);\n", s->name, s->name, s->name); Lappendstr(procfunc, buf); }else{ Lappendstr(procfunc, "_theta = _xi - (double)_i;\n"); ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "for (_j = 0; _j < %d; _j++) {double *_t = _t_%s[_j];", s->araydim, s->name); Lappendstr(procfunc, buf); Sprintf(buf, "%s[_j] = _t[_i] + _theta*(_t[_i+1] - _t[_i]);}\n", s->name); }else{ Sprintf(buf, "%s = _t_%s[_i] + _theta*(_t_%s[_i+1] - _t_%s[_i]);\n", s->name, s->name, s->name, s->name); } Lappendstr(procfunc, buf); } } Lappendstr(procfunc, "}\n\n"); /* end of new function */ /* table declaration */ ITERATE(q, table) { s = SYM(q); if (s->subtype & ARRAY) { Sprintf(buf, "static double *_t_%s[%d];\n", s->name, s->araydim); }else{ Sprintf(buf, "static double *_t_%s;\n", s->name); } Lappendstr(firstlist, buf); } /*cleanup*/ freelist(&table); freelist(&depend); freelist(&from); freelist(&to); } #if HMODL || NMODL void hocfunchack(Symbol* n, Item* qpar1, Item* qpar2, int hack) { #if NOCMODL extern int point_process; #endif Item *q; int i; #if VECTORIZE Item* qp=0; #endif #if BBCORE Lappendstr(procfunc, "\n#if 0 /*BBCORE*/\n"); #endif if (point_process) { Sprintf(buf, "\nstatic double _hoc_%s(void* _vptr) {\n double _r;\n", n->name); }else{ Sprintf(buf, "\nstatic void _hoc_%s(void) {\n double _r;\n", n->name); } Lappendstr(procfunc, buf); vectorize_substitute(lappendstr(procfunc, ""), "\ double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt;\n\ "); if (point_process) { vectorize_substitute(lappendstr(procfunc, " _hoc_setdata(_vptr);\n"), "\ _p = ((Point_process*)_vptr)->_prop->param;\n\ _ppvar = ((Point_process*)_vptr)->_prop->dparam;\n\ _thread = _extcall_thread;\n\ _nt = (NrnThread*)((Point_process*)_vptr)->_vnt;\n\ "); }else{ vectorize_substitute(lappendstr(procfunc, ""), "\ if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; }\n\ _thread = _extcall_thread;\n\ _nt = nrn_threads;\n\ "); } #if VECTORIZE if (n == last_func_using_table) { qp = lappendstr(procfunc, ""); sprintf(buf,"\n#if 1\n _check_%s(_threadargs_);\n#endif\n", n->name); vectorize_substitute(qp, buf); } #endif if (n->subtype & FUNCT) { Lappendstr(procfunc, "_r = "); }else{ Lappendstr(procfunc, "_r = 1.;\n"); } Lappendsym(procfunc, n); lappendstr(procfunc, "("); #if VECTORIZE qp = lappendstr(procfunc, ""); #endif for (i=0; i < n->varnum; ++i) { Sprintf(buf, "*getarg(%d)", i+1); Lappendstr(procfunc, buf); if (i+1 < n->varnum) { Lappendstr(procfunc, ","); } } #if NOCMODL if (point_process) { Lappendstr(procfunc, ");\n return(_r);\n}\n"); }else #endif Lappendstr(procfunc, ";\n hoc_retpushx(_r);\n}\n"); #if BBCORE Lappendstr(procfunc, "\n#endif /*BBCORE*/\n"); #endif #if VECTORIZE if (i) { vectorize_substitute(qp, "_threadargs_,"); }else if (!hack) { vectorize_substitute(qp, "_threadargs_"); } #endif } void hocfunc(n, qpar1, qpar2) /*interface between modl and hoc for proc and func */ Item *qpar1, *qpar2; Symbol *n; { /* Hack prevents FUNCTION_TABLE bug of 'double table_name()' extra args replacing the double in 'double name(...) */ hocfunchack(n, qpar1, qpar2, 0); } void acc_net_add(Item* qname, Item* qpar1, Item* qexpr, Item* qpar2, const char* xarg1, const char* xarg2) { Item *q; if (artificial_cell) { return; } sprintf(buf, "\ \n#if NET_RECEIVE_BUFFERING\ \n _net_send_buffering(_ml->_net_send_buffer, %s\ ", xarg1); Insertstr(qname, buf); for (q = qpar1->next; q != qpar2; q = q->next) { if (q->itemtype == SYMBOL) { insertsym(qname, SYM(q)); }else if (q->itemtype == STRING) { insertstr(qname, STR(q)); }else{ diag("acc_net_add failed because item neither STRING nor SYMBOL"); } } sprintf(buf, "%s);\n#else\n", xarg2); Insertstr(qname, buf); Insertstr(qpar2->next, "\n#endif\n"); } #if VECTORIZE /* ARGSUSED */ void vectorize_use_func(qname, qpar1, qexpr, qpar2, blocktype) Item* qname, *qpar1, *qexpr, *qpar2; int blocktype; { Item* q; if (SYM(qname)->subtype & EXTDEF) { if (strcmp(SYM(qname)->name, "nrn_pointing") == 0) { Insertstr(qpar1->next, "&"); }else if (strcmp(SYM(qname)->name, "state_discontinuity") == 0) { #if CVODE fprintf(stderr, "Notice: Use of state_discontinuity is not thread safe"); vectorize = 0; if (blocktype == NETRECEIVE) { Fprintf(stderr, "Notice: Use of state_discontinuity in a NET_RECEIVE block is unnecessary and prevents use of this mechanism in a multithreaded simulation.\n"); } if (!state_discon_list_) { state_discon_list_ = newlist(); } lappenditem(state_discon_list_, qpar1->next); #endif Insertstr(qpar1->next, "-1, &"); }else if (strcmp(SYM(qname)->name, "net_send") == 0) { net_send_seen_ = 1; if (artificial_cell) { replacstr(qname, "artcell_net_send"); } Insertstr(qexpr, "t + "); if (blocktype == NETRECEIVE) { acc_net_add(qname, qpar1, qexpr, qpar2, "0, _tqitem, _weight_index, _ppvar[1*_STRIDE],", ""); Insertstr(qpar1->next, "_tqitem, _weight_index, _pnt,"); }else if (blocktype == INITIAL1){ net_send_buffer_in_initial = 1; acc_net_add(qname, qpar1, qexpr, qpar2, "0, _tqitem, 0, _ppvar[1*_STRIDE],", ""); Insertstr(qpar1->next, "_tqitem, -1, (Point_process*) _nt->_vdata[_ppvar[1*_STRIDE]],"); }else{ diag("net_send allowed only in INITIAL and NET_RECEIVE blocks", (char*)0); } }else if (strcmp(SYM(qname)->name, "net_event") == 0) { net_event_seen_ = 1; if (blocktype == NETRECEIVE) { acc_net_add(qname, qpar1, qexpr, qpar2, "1, -1, -1, _ppvar[1*_STRIDE],", ", 0."); Insertstr(qpar1->next, "_pnt,"); }else{ diag("net_event", " only allowed in NET_RECEIVE block"); } }else if (strcmp(SYM(qname)->name, "net_move") == 0) { if (artificial_cell) { replacstr(qname, "artcell_net_move"); } if (blocktype == NETRECEIVE) { acc_net_add(qname, qpar1, qexpr, qpar2, "2, _tqitem, -1, _ppvar[1*_STRIDE],", ", 0."); Insertstr(qpar1->next, "_tqitem, _pnt,"); }else{ diag("net_move", " only allowed in NET_RECEIVE block"); } } return; } #if 1 if (qexpr) { q = insertstr(qpar1->next, "_threadargscomma_"); }else{ q = insertstr(qpar1->next, "_threadargs_"); } #else q = insertstr(qpar1->next, ""); if (qexpr) { vectorize_substitute(q, "_threadargs_,"); }else{ vectorize_substitute(q, "_threadargs_"); } #endif } #endif #endif void function_table(s, qpar1, qpar2, qb1, qb2) /* s ( ... ) { ... } */ Symbol* s; Item *qpar1, *qpar2, *qb1, *qb2; { Symbol* t; int i; Item* q, *q1, *q2; for (i=0, q=qpar1->next; q != qpar2; q = q->next) { #if VECTORIZE if (q->itemtype == STRING || SYM(q)->name[0] != '_') { continue; } #endif sprintf(buf, "_arg[%d] = %s;\n", i, SYM(q)->name); insertstr(qb2, buf); ++i; } if (i == 0) { diag("FUNCTION_TABLE declaration must have one or more arguments:", s->name); } sprintf(buf, "double _arg[%d];\n", i); insertstr(qb1->next, buf); sprintf(buf, "return hoc_func_table(_ptable_%s, %d, _arg);\n", s->name, i); insertstr(qb2, buf); insertstr(qb2, "}\n/* "); /* kludge to avoid a bad vectorize_substitute */ insertstr(qb2->next, " */\n"); sprintf(buf, "table_%s", s->name); t = install(buf, NAME); t->subtype |= FUNCT; t->usage |= FUNCT; t->no_threadargs = 1; t->varnum = 0; sprintf(buf,"double %s", t->name); lappendstr(procfunc, buf); q1 = lappendsym(procfunc, SYM(qpar1)); q2 = lappendsym(procfunc, SYM(qpar2)); sprintf(buf,"{\n\thoc_spec_table(&_ptable_%s, %d);\n\treturn 0.;\n}\n", s->name, i); lappendstr(procfunc, buf); sprintf(buf, "\nstatic void* _ptable_%s = (void*)0;\n", s->name); linsertstr(procfunc, buf); hocfunchack(t, q1, q2, 1); } void watchstmt(par1, dir, par2, flag, blocktype )Item *par1, *dir, *par2, *flag; int blocktype; { if (!watch_seen_) { ++watch_seen_; watch_data_ = newlist(); } if (blocktype != NETRECEIVE) { diag("\"WATCH\" statement only allowed in NET_RECEIVE block", (char*)0); } #if 0 sprintf(buf, "\nstatic double _watch%d_cond(_pnt) Point_process* _pnt; {\n", watch_seen_); lappendstr(procfunc, buf); vectorize_substitute(lappendstr(procfunc, ""),"\tdouble* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt;\n\t_thread= (Datum*)0; _nt = (NrnThread*)_pnt->_vnt;\n"); sprintf(buf, "\t_p = _pnt->_prop->param; _ppvar = _pnt->_prop->dparam;\n\tv = VEC_V(_ml->_nodeindices[_iml]));\n return "); lappendstr(procfunc, buf); movelist(par1, par2, procfunc); movelist(dir->next, par2, procfunc); if (SYM(dir)->name[0] == '<') { insertstr(par1, "-("); insertstr(par2->next, ")"); } replacstr(dir, ") - ("); lappendstr(procfunc, ";\n}\n"); sprintf(buf, " _nrn_watch_activate(_watch_array, _watch%d_cond, %d, _pnt, _watch_rm++, %s);\n", watch_seen_, watch_seen_, STR(flag)); replacstr(flag, buf); #endif sprintf(buf, "_nrn_watch_activate(%d) ", watch_seen_); insertstr(par1, buf); insertstr(flag, "; /*"); insertstr(flag->next, "*/\n"); lappenditem(watch_data_, par1); lappenditem(watch_data_, par2); lappenditem(watch_data_, flag); ++watch_seen_; } void threadsafe(char* s) { if (!assert_threadsafe) { fprintf(stderr, "Notice: %s\n", s); vectorize = 0; } } Item* protect_astmt(Item* q1, Item* q2) { /* PROTECT, ';' */ Item* q; replacstr(q1, "/* PROTECT */_NMODLMUTEXLOCK\n"); q = insertstr(q2->next, "\n _NMODLMUTEXUNLOCK /* end PROTECT */\n"); protect_include_ = 1; return q; } void nrnmutex(int on, Item* q) { /* MUTEXLOCK or MUTEXUNLOCK */ static int toggle = 0; if (on == 1) { if (toggle != 0) { diag("MUTEXLOCK invoked after MUTEXLOCK", (char*)0); } toggle = 1; replacstr(q, "_NMODLMUTEXLOCK\n"); protect_include_ = 1; }else if (on == 0) { if (toggle != 1) { diag("MUTEXUNLOCK invoked with no earlier MUTEXLOCK", (char*)0); } toggle = 0; replacstr(q, "_NMODLMUTEXUNLOCK\n"); protect_include_ = 1; }else{ if (toggle != 0) { diag("MUTEXUNLOCK not invoked after MUTEXLOCK", (char*)0); } toggle = 0; } } mod2c-8.2.2/src/mod2c_core/parse1.y000066400000000000000000001053761425457616700167540ustar00rootroot00000000000000%{ /* /local/src/master/nrn/src/nmodl/parse1.y,v 4.11 1999/03/24 18:34:08 hines Exp */ #include "nmodlconf.h" #include "modl.h" #include #if defined(__STDC__) #define sdebug(arg1,arg2) {} #define qdebug(arg1,arg2) {} #else #define sdebug(arg1,arg2) {Fprintf(stderr,"arg1:%s\n", arg2); Fflush(stderr);} #define qdebug(arg1,arg2) {Item *q; Fprintf(stderr,"arg1:");Fflush(stderr);\ for (q=arg2; q->type != 0; q=q->next){\ if (q->type == SYMBOL)\ Fprintf(stderr,"%s\n", SYM(q)->name);\ else if (q->type == STRING)\ Fprintf(stderr,"%s\n", STR(q);\ else\ Fprintf(stderr,"Illegal Item type\n");\ Fflush(stderr);}\ Fprintf(stderr,"\n");Fflush(stderr);} #endif #define ldebug(arg1, arg2) qdebug(arg1, arg2->next) extern int yylex(), yyparse(); static void yyerror(); #if YYBISON #define myerr(arg) static int ierr=0;\ if (!(ierr++))yyerror(arg); --yyssp; --yyvsp; YYERROR #else #define myerr(arg) static int ierr=0;\ if (!(ierr++))yyerror(arg); --yyps; --yypv; YYERROR #endif int brkpnt_exists; int assert_threadsafe; int usederivstatearray; extern int protect_; extern int vectorize; extern int in_comment_; /* allow non-ascii in a COMMENT */ extern char *modelline; extern Item* protect_astmt(Item*, Item*); extern List* toplocal_; static List* toplocal1_; extern List *firstlist; /* NAME symbols in order that they appear in file */ extern List* units_def_for_acc; /* might not be a SUFFIX when declared */ extern int lexcontext; /* ':' can return 3 different tokens */ extern List *solveforlist; /* List of symbols that are actually to be solved for in a block. See in_solvefor() */ static int stateblock; /* 0 if dependent, 1 if state */ static int blocktype; static int saw_verbatim_; /* only print the notice once */ static int inequation; /* inside an equation?*/ static int nstate; /* number of states seen in an expression */ static int leftside; /* inside left hand side of equation? */ static int pstate; /* number of state in a primary expression */ static int tstate; /* number of states in a term */ static Item *lastok; /* last token accepted by expr */ static int sensused; /* a SENS statement occurred in this block */ static Symbol *matchindex; /* local symbol for implied MATCH loop */ static int model_level = 0; /* the model level prepended to declaration blocks by merge */ static int scopindep = 0;/* SCoP independent explicitly declared if 1 */ static int extdef2 = 0; /* flag that says we are in an EXTDEF2 function */ static List *table_list = LIST0; /* table information for TABLE statement */ static int forallindex = 0; /* 0 not in FORALL, -1 just starting, >0 index of arrays used (must all be the same */ static Item* astmt_end_; /* see kinetic.c vectorizing */ static int nr_argcnt_, argcnt_; /* for matching number of args in NET_RECEIVE and FOR_NETCONS */ %} %union { Item *qp; char *str; List *lp; int i; } %token VERBATIM COMMENT MODEL CONSTANT INDEPENDENT DEPENDENT STATE %token INITIAL1 DERIVATIVE SOLVE USING WITH STEPPED DISCRETE %token FROM FORALL1 TO BY WHILE IF ELSE START1 STEP SENS SOLVEFOR %token PROCEDURE PARTIAL DEL DEL2 DEFINE1 IFERROR PARAMETER %token DERFUNC EQUATION TERMINAL LINEAR NONLINEAR FUNCTION1 LOCAL %token METHOD LIN1 NONLIN1 PUTQ GETQ TABLE DEPEND BREAKPOINT %token INCLUDE1 FUNCTION_TABLE PROTECT NRNMUTEXLOCK NRNMUTEXUNLOCK %token '{' '}' '(' ')' '[' ']' '@' '+' '*' '-' '/' '=' '^' ':' ',' %token '~' %token OR AND GT LT LE EQ NE NOT %token NAME PRIME REAL INTEGER DEFINEDVAR %type Name NUMBER real intexpr integer %token STRING PLOT VS LAG RESET MATCH MODEL_LEVEL SWEEP FIRST LAST %type line model units optindex unit limits abstol %type name number nonlineqn primary term linexpr numlist %type expr aexpr ostmt astmt stmtlist locallist locallist1 %type varname exprlist define1 queuestmt %type asgn fromstmt whilestmt ifstmt solveblk funccall ifsolerr %type opinc opstart senslist sens lagstmt forallstmt %type parmasgn stepped indepdef depdef withby %type declare parmblk indepblk depblk stateblk stepblk %type watchstmt watchdir watch1 fornetcon %type plotdecl constblk %type matchblk matchlist match matchname pareqn firstlast %token KINETIC CONSERVE REACTION REACT1 COMPARTMENT UNITS %token UNITSON UNITSOFF LONGDIFUS %type reaction conserve react compart ldifus namelist unitblk %type solvefor solvefor1 uniton %type tablst tablst1 dependlst arglist arglist1 %type locoptarray /* interface to NEURON */ %token NEURON SUFFIX NONSPECIFIC READ WRITE USEION VALENCE THREADSAFE %token GLOBAL SECTION RANGE POINTER BBCOREPOINTER EXTERNAL BEFORE AFTER WATCH %token ELECTRODE_CURRENT CONSTRUCTOR DESTRUCTOR NETRECEIVE FOR_NETCONS %type neuronblk nrnuse nrnlist optnrnlist valence initstmt bablk %token CONDUCTANCE %type conducthint /* precedence in expressions--- low to high */ %left OR %left AND %left GT GE LT LE EQ NE %left '+' '-' /* left associative, same precedence */ %left '*' '/' '%'/* left assoc., higher precedence */ %left UNARYMINUS NOT %right '^' /* exponentiation */ %% top: all {/*ldebug(top, intoken)*/;} |error {diag("Illegal block", (char *)0);} ; all: /*nothing*/ | all model | all locallist /* move the declarations into firstlist */ {Item* q; replacstr($2, "static double"); vectorize_substitute($2, "/*Top LOCAL"); vectorize_substitute(lastok->next, "*/\n"); movelist($2, lastok->next, firstlist); if (!toplocal_) {toplocal_ = newlist();} ITERATE(q, toplocal1_) { assert(SYM(q)->name[0] == '_' && SYM(q)->name[1] == 'l'); SYM(q)->name[1] = 'z'; } movelist(toplocal1_->next, toplocal1_->prev, toplocal_); } | all define1 | all declare | all MODEL_LEVEL INTEGER {model_level = atoi(STR($3));} declare {model_level = 0;} | all {if (sensused) diag("sensitivity analysis not implemented for", " this block type"); } proc | all VERBATIM /* read everything and move as is to end of procfunc */ { Lappendstr(procfunc, "} using namespace coreneuron;"); inblock(SYM($2)->name); replacstr($2, "\n/*VERBATIM*/\n"); if (!assert_threadsafe && !saw_verbatim_) { fprintf(stderr, "Notice: VERBATIM blocks are not thread safe\n"); saw_verbatim_ = 1; vectorize = 0; } movelist($2,intoken->prev, procfunc); Lappendstr(procfunc, "namespace coreneuron {"); } | all COMMENT /* read everything and delete */ { in_comment_ = 1; inblock(SYM($2)->name); deltokens($2, intoken->prev); in_comment_ = 0; } | all uniton | all INCLUDE1 STRING {include_file($3);} ; model: MODEL line {if (modelline == NULL) modelline = $2; deltokens($1, intoken->prev);} ; line: {$$ = inputline();} ; define1: DEFINE1 NAME INTEGER /* all subsequent occurences of NAME will be replaced by integer during parseing. See 'integer:' */ { Symbol *sp = SYM($2); if (sp->subtype) diag(sp->name, " used before DEFINEed"); sp->u.str = STR($3); sp->type = DEFINEDVAR; deltokens($1, $3);} | DEFINE1 error {myerr("syntax: DEFINE name integer");} ; Name: NAME { Symbol *checklocal(); SYM($1) = checklocal(SYM($1)); /* it was a bug when this was done to the lookahead token in lex */ } ; declare: parmblk | indepblk | depblk | stateblk | stepblk | plotdecl | neuronblk | unitblk | constblk ; parmblk: PARAMETER '{' parmbody '}' {deltokens($1, $4);} ; parmbody: /*nothing*/ | parmbody parmasgn { explicit_decl(model_level, $2);} /* | parmbody stepped */ /*now has its own block*/ ; parmasgn: NAME '=' number units limits /* install in syminorder and put info in Symbol->u.str Note that usage is EXPLICIT_DECL */ {parminstall(SYM($1), STR($3), $4, $5);} | NAME units limits {parminstall(SYM($1), "0", $2, $3);} | NAME '[' integer ']' units limits { int i = atoi(STR($3)); if (i < 1) diag("Array index must be > 0", (char*)0); parm_array_install(SYM($1), "0", $5, $6, i); } | error {diag("name = number", (char *)0);} ; units: /*nothing*/ {$$ = stralloc("", (char *)0);} | unit ; unit: '(' {$$ = inputtopar();} /*string*/ ')' /*does not include parentheses*/ {$$ = $2; delete($1); delete($3);} ; uniton: UNITSON {replacstr($1, "");} | UNITSOFF {replacstr($1, "");} ; limits: /*nothing*/ {$$ = stralloc("", (char*)0);} | LT real ',' real GT { Sprintf(buf, "%s %s", STR($2), STR($4)); $$ = stralloc(buf, (char*)0); } ; stepblk: STEPPED '{' stepbdy '}' {deltokens($1, $4);} ; stepbdy: /*nothing*/ | stepbdy stepped { explicit_decl(model_level, $2); } ; stepped: NAME '=' numlist units /* install */ {steppedinstall(SYM($1), $3, lastok, $4);} ; numlist: number ',' number | numlist ',' number ; name: Name | PRIME ; number: NUMBER {lastok = $1;} | '-' NUMBER /* replace the string with -string and discard '-'*/ { Sprintf(buf, "-%s", STR($2)); STR($2) = stralloc(buf, STR($2)); $$ = $2; delete($1); lastok = $2; } ; NUMBER: integer | REAL ; integer: INTEGER | DEFINEDVAR {replacstr($1, SYM($1)->u.str);} ; real: REAL {lastok = $1;} | integer /* add a .0 to the string */ {Sprintf(buf, "%s.0", STR($1)); STR($1) = stralloc(buf, STR($1)); lastok = $1; } ; indepblk: INDEPENDENT '{' indepbody '}' {deltokens($1, $4);} ; indepbody: /*nothing*/ | indepbody indepdef { explicit_decl(model_level, $2); } | indepbody SWEEP {scopindep = 1;} indepdef { explicit_decl(model_level, $4); scopindep = 0; } ; indepdef: NAME FROM number TO number withby integer opstart units /*indepinstall()*/ {indepinstall(SYM($1), STR($3), STR($5), STR($7), $8, $9, scopindep); } | error {diag("name FROM number TO number WITH integer\n", (char *)0);} ; withby: WITH ; depblk: DEPENDENT {stateblock = 0;} '{' depbody '}' {deltokens($1, $5);} ; depbody: /*nothing*/ | depbody depdef { explicit_decl(model_level, $2);} ; depdef: name opstart units abstol /*depinstall()*/ {depinstall(stateblock, SYM($1), 0, "0", "1", $3, $2, 1, $4); } | name '[' integer ']' opstart units abstol {int i = atoi(STR($3)); if (i < 1) diag("Array index must be > 0", (char *)0); depinstall(stateblock, SYM($1), i, "0", "1", $6, $5, 1, $7); } | name FROM number TO number opstart units abstol {depinstall(stateblock, SYM($1), 0, STR($3), STR($5), $7, $6, 1, $8); } | name '[' integer ']' FROM number TO number opstart units abstol {int i = atoi(STR($3)); if (i < 1) diag("Array index must be > 0", (char *)0); depinstall(stateblock, SYM($1), i, STR($6), STR($8), $10, $9, 1, $11); } | error { diag("name FROM number TO number START number\n", "FROM...TO and START are optional, name can be name[integer]\n");} ; opstart: /*nothing*/ {$$ = ITEM0;} | START1 number {$$ = $2;} ; abstol: /*nothing*/ { $$ = stralloc("", (char*)0);} | LT real GT { $$ = stralloc(STR($2), (char*)0); } ; stateblk: STATE {stateblock = 1;} '{' depbody '}' {deltokens($1, $5);} ; plotdecl: PLOT pvlist VS name optindex /* construct plotlist. Used in parout.c */ { Item *q; q = linsertsym(plotlist, SYM($4)); Insertstr(q->next, $5); } | PLOT error { diag("PLOT namelist VS name", (char *)0);} ; pvlist: name optindex { if (plotlist->next == plotlist) { Lappendsym(plotlist, SYM($1)); Lappendstr(plotlist, $2); }else{ diag("Only one PLOT declaration allowed", (char *)0); } } | pvlist ',' name optindex { Lappendsym(plotlist, SYM($3)); Lappendstr(plotlist, $4);} ; optindex: /*nothing*/ { $$ = "-1";} | '[' INTEGER ']' { $$ = STR($2);} ; proc: {blocktype = INITIAL1;} initblk /*blocktype set prior to parsing*/ | {lexcontext = NONLINEAR; blocktype = DERIVATIVE;} derivblk | {blocktype = BREAKPOINT;} brkptblk | {lexcontext = blocktype = LINEAR;} linblk | {lexcontext = blocktype = NONLINEAR;} nonlinblk | {blocktype = FUNCTION1;} funcblk | {blocktype = PROCEDURE;} procedblk | {blocktype = NETRECEIVE;} netrecblk | {blocktype = TERMINAL;} terminalblk | {blocktype = DISCRETE;} discretblk | {lexcontext = blocktype = PARTIAL;} partialblk | {lexcontext = blocktype = KINETIC;ostmt_start();} kineticblk {see_ostmt();} | {blocktype = CONSTRUCTOR;} constructblk | {blocktype = DESTRUCTOR;} destructblk | {blocktype = FUNCTION_TABLE;} functableblk | {blocktype = BEFORE;} BEFORE bablk | {blocktype = AFTER;} AFTER bablk ; initblk: INITIAL1 stmtlist '}' {movelist($2, $3, initfunc);} ; constructblk: CONSTRUCTOR stmtlist '}' {movelist($2, $3, constructorfunc);} ; destructblk: DESTRUCTOR stmtlist '}' {movelist($2, $3, destructorfunc);} ; stmtlist: '{' {pushlocal();} stmtlist1 {poplocal();} | '{' locallist stmtlist1 {poplocal();} ; conducthint: CONDUCTANCE Name {conductance_hint(blocktype, $1, $2);} | CONDUCTANCE Name USEION NAME {conductance_hint(blocktype, $1, $4);} ; locallist: LOCAL { if (toplocal1_) {freelist(&toplocal1_);} toplocal1_ = newlist(); } locallist1 { replacstr($1, "double"); Insertstr(lastok->next, ";\n"); possible_local_current(blocktype, toplocal1_); } | LOCAL error {myerr("Illegal LOCAL declaration");} ; locallist1: NAME locoptarray /* locals are placed in a stack of symbol lists and given the prefix _l */ {int a2; pushlocal(); a2 = SYM($1)->assigned_to_; /* in case marked threadsafe */ SYM($1) = copylocal(SYM($1)); SYM($1)->assigned_to_ = a2; lappendsym(toplocal1_, SYM($1)); if ($2) { SYM($1)->araydim = $2; SYM($1)->subtype |= ARRAY; }else{ lastok = $1; } } | locallist1 ',' NAME locoptarray { int a2 = SYM($3)->assigned_to_; /* in case marked threadsafe */ SYM($3) = copylocal(SYM($3)); SYM($3)->assigned_to_ = a2; lappendsym(toplocal1_, SYM($3)); if ($4) { SYM($3)->araydim = $4; SYM($3)->subtype |= ARRAY; }else{ lastok = $3; } } ; locoptarray: /*nothing*/ {$$ = 0;} | '[' integer ']' {$$ = atoi(STR($2)); lastok = $3;} ; stmtlist1: /*nothing*/ | stmtlist1 {if (blocktype == KINETIC) see_ostmt();} ostmt {if (blocktype == KINETIC) see_ostmt();} | stmtlist1 astmt {if (blocktype == KINETIC) { see_astmt($2, astmt_end_); }} ; ostmt: fromstmt | forallstmt | whilestmt | ifstmt | stmtlist '}' | solveblk | conducthint | VERBATIM {inblock(SYM($1)->name); replacstr($1, "\n/*VERBATIM*/\n"); if (!assert_threadsafe && !saw_verbatim_) { fprintf(stderr, "Notice: VERBATIM blocks are not thread safe\n"); saw_verbatim_ = 1; vectorize = 0; } } | COMMENT {inblock(SYM($1)->name); deltokens($1, intoken->prev);} | sens | compart {check_block(KINETIC, blocktype, "COMPARTMENT");} | ldifus {check_block(KINETIC, blocktype, "LONGDIFUS");} | conserve {check_block(KINETIC, blocktype, "CONSERVE");} | lagstmt | queuestmt | RESET { replacstr($1, " _reset = 1;\n"); } | matchblk | pareqn /* 2nd order partial equation and boundary conditions*/ | tablestmt {if (blocktype !=FUNCTION1 && blocktype != PROCEDURE) { diag("TABLE valid only for FUNCTION or PROCEDURE", (char *)0); }} | uniton | initstmt | watchstmt | fornetcon | NRNMUTEXLOCK { nrnmutex(1,$1); } | NRNMUTEXUNLOCK { nrnmutex(0,$1); } | error {myerr("Illegal statement");} ; astmt: asgn /* ';' is added when relevant */ {astmt_end_ = insertsym(lastok->next, semi);} | PROTECT {protect_ = 1;} asgn {protect_ = 0; astmt_end_ = insertsym(lastok->next, semi); astmt_end_ = protect_astmt($1, astmt_end_); } | {inequation = 1;} reaction { $$ = $2; inequation = 0; astmt_end_ = insertstr(lastok->next->next->next, "");} | funccall {astmt_end_ = insertsym(lastok->next, semi);} ; asgn: varname '=' expr /* depending on blocktype, varname may get marked as used. */ { if (blocktype == DERIVATIVE && SYM($1)->type == PRIME) { /* put Dvar in a derivative used list */ deriv_used(SYM($1), $3, lastok); } if (blocktype == DERIVATIVE && (SYM($1)->subtype & STAT)) { Fprintf(stderr, "WARNING: %s (a STATE) is assigned a value\ in a DERIVATIVE block.\n Multistep integrators (such as Runge) may not\ work correctly.\n", SYM($1)->name); } if (blocktype == DISCRETE && SYM($1)->type == NAME && (SYM($1)->subtype & STAT)) { SYM($1)->used++; } #if NOCMODL nrn_var_assigned(SYM($1)); #endif } | nonlineqn expr '=' expr /* put info in equation list */ { inequation = 0; Insertstr($2, " -("); replacstr($3, ") + "); if (nstate == 0) {yyerror("previous equation contains no state variables"); YYERROR;} eqnqueue($1); } | lineqn leftlinexpr '=' linexpr { inequation = 0; delete($3); if (nstate == 0) {yyerror("previous equation contains no state variables"); YYERROR;} } ; varname: name /* much marking depending on context */ {lastok = $1; if (!extdef2){SYM($1)->usage |= DEP;} if (SYM($1)->subtype & ARRAY && !extdef2) {myerr("variable needs an index");} if (inequation && (SYM($1)->subtype & STAT) && in_solvefor(SYM($1))) { SYM($1)->used++; nstate++; pstate++; tstate++; } if (SYM($1)->subtype & INTGER) { lastok = insertstr($1->next, ")"); $1 = insertstr($1, "((double)"); } } | name '[' intexpr ']' {lastok = $4; if (SYM($1)->type == PRIME) { usederivstatearray = 1; } SYM($1)->usage |= DEP; if ((SYM($1)->subtype & ARRAY) == 0) {myerr("variable is not an array");} if (inequation && (SYM($1)->subtype & STAT) && in_solvefor(SYM($1))) { SYM($1)->used++; nstate++; pstate++; tstate++; } if (forallindex) { if (forallindex == -1) { forallindex = SYM($1)->araydim; } if (forallindex != SYM($1)->araydim) { Sprintf(buf, "%s dimension not same as other dimensions used in FORALL statement", SYM($1)->name); diag(buf, (char *)0); } } } | NAME '@' integer {lastok = $3; SYM($1)->usage |= DEP; disc_var_seen($1, $2, $3, 0);} | NAME '@' integer '[' intexpr ']' {lastok = $6; SYM($1)->usage |= DEP; disc_var_seen($1, $2, $3, ARRAY);} ; intexpr: Name {lastok = $1; SYM($1)->usage |= DEP; if (!(SYM($1)->subtype & INTGER)) { lastok = insertstr($1->next, ")"); $1 = insertstr($1, "((int)"); } } | integer { lastok = $1;} | '(' intexpr ')' { lastok = $3;} | intexpr '+' intexpr | intexpr '-' intexpr | intexpr '*' intexpr | intexpr '/' intexpr | error {myerr("Illegal integer expression");} ; expr: varname | real units | funccall | '(' expr ')' {lastok = $3;} | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '^' expr /* converted to pow() */ { $$ = insertstr($1, "pow("); replacstr($2, ","); lastok = insertstr(lastok->next, ")"); } | expr OR expr {replacstr($2, " ||");} | expr AND expr {replacstr($2, " &&");} | expr GT expr | expr LT expr | expr GE expr | expr LE expr | expr EQ expr {replacstr($2, " ==");} | expr NE expr {replacstr($2, " !=");} | NOT expr {replacstr($1, " !");} | '-' expr %prec UNARYMINUS | error {myerr("Illegal expression");} ; nonlineqn: NONLIN1 {inequation = 1; nstate = 0;} ; lineqn: LIN1 /* initialize a bunch of equation info */ {inequation = 1; nstate = 0; pstate = 0; tstate = 0; init_lineq($1); leftside = -1;} ; leftlinexpr: linexpr {leftside = 1;} ; linexpr: primary /* put terms in a list */ {linterm($1, lastok, pstate, leftside); pstate = 0;} | '-' primary {delete($1); linterm($2, lastok, pstate, -leftside); pstate = 0;} | linexpr '+' primary {delete($2); linterm($3, lastok, pstate, leftside); pstate = 0;} | linexpr '-' primary {delete($2); linterm($3, lastok, pstate, -leftside); pstate = 0;} ; primary: term { if (tstate == 1) { lin_state_term($1, lastok); } tstate = 0; } | primary '*' term { if (tstate == 1) { lin_state_term($3, lastok); } tstate = 0; } | primary '/' term { if (tstate) { diag("state ocurs in denominator", (char *)0); } } ; term: varname | real | funccall {if (tstate) diag("states not permitted in function calls", (char *)0);} | '(' expr ')' { lastok = $3; if (tstate) diag("states not permitted between ", "parentheses");} | error {diag("Some operators are not permitted in linear\n", "expressions unless the terms containing them are\nenclosed in parentheses");} ; funccall: NAME '(' { if (SYM($1)->subtype & EXTDEF2) { extdef2 = 1;}} exprlist ')' {lastok = $5; SYM($1)->usage |= FUNCT; if (SYM($1)->subtype & EXTDEF2) { extdef2 = 0;} if (SYM($1)->subtype & EXTDEF3) { add_reset_args($2);} if (SYM($1)->subtype & EXTDEF4) { add_nrnthread_arg($2);} if (SYM($1)->subtype & EXTDEF5) { if (!assert_threadsafe) { fprintf(stderr, "Notice: %s is not thread safe\n", SYM($1)->name); vectorize = 0; } } #if VECTORIZE vectorize_use_func($1,$2,$4,$5,blocktype); #endif } ; exprlist: /*nothing*/{$$ = ITEM0;} | expr | STRING | exprlist ',' expr | exprlist ',' STRING ; fromstmt: FROM NAME {pushlocal(); SYM($2) = copylocal(SYM($2)); SYM($2)->subtype |= INTGER;} '=' intexpr TO intexpr opinc stmtlist '}' /* translate the whole thing using _lNAME as an integer */ { replacstr($1, "{int "); poplocal(); Insertstr($4, ";for ("); Insertstr($4, SYM($2)->name); Insertstr($6, ";"); Insertstr($6, SYM($2)->name); replacstr($6, "<="); if ($8) { Insertstr($8, ";"); Insertstr($8, SYM($2)->name); replacstr($8, "+="); } else { Insertstr($9, ";"); Insertstr($9, SYM($2)->name); Insertstr($9, "++"); } Insertstr($9, ")"); Insertstr($10, "}"); } |FROM error { myerr("FROM intvar = intexpr TO intexpr BY intexpr { statements }");} ; opinc: /*nothing*/ {$$ = ITEM0;} | BY intexpr ; forallstmt: FORALL1 NAME {pushlocal(); SYM($2) = copylocal(SYM($2)); SYM($2)->subtype |= INTGER; if (forallindex) { diag("Nested FORALL statements not allowed", (char *)0); } forallindex = -1; } stmtlist '}' /* translate the whole thing using _lNAME as an integer */ { replacstr($1, "{int "); poplocal(); if (forallindex == -1) { diag("FORALL range is undefined since no arrays used", " within the statement"); } Sprintf(buf, "; for (%s=0; %s<%d; %s++)", SYM($2)->name, SYM($2)->name, forallindex, SYM($2)->name); Insertstr($4, buf); Insertstr($5, "}"); } |FORALL1 error { myerr("FORALL intvar { statements }");} ; whilestmt: WHILE '(' expr ')' stmtlist '}' ; ifstmt: IF '(' expr ')' stmtlist '}' optelseif optelse ; optelseif: /*nothing*/ | optelseif ELSE IF '(' expr ')' stmtlist '}' { #if VECTORIZE vectorize_if_else_stmt(blocktype); #endif } ; optelse: /*nothing*/ | ELSE stmtlist '}' { #if VECTORIZE vectorize_if_else_stmt(blocktype); #endif } ; derivblk: DERIVATIVE NAME stmtlist '}' /* process using massagederiv() */ {massagederiv($1, $2, $3, $4, sensused); sensused = 0;} ; linblk: LINEAR NAME solvefor {init_linblk($2);} stmtlist '}' /*massage_linblk()*/ {massage_linblk($1, $2, $5, $6, sensused); lexcontext = 0; sensused = 0; } ; nonlinblk: NONLINEAR NAME solvefor stmtlist '}' /*massagenonlin()*/ {massagenonlin($1, $2, $4, $5, sensused); lexcontext = 0; sensused = 0; } ; discretblk: DISCRETE NAME stmtlist '}' /*massagediscblk()*/ {massagediscblk($1, $2, $3, $4);} ; partialblk: PARTIAL NAME stmtlist '}' /*massagepartial()*/ {massagepartial($1, $2, $3, $4); lexcontext = 0; } | PARTIAL error { diag("within the PARTIAL block must occur an equation with the syntax ---\n", "~ V' = F*DEL2(V) + G\n"); } ; pareqn: '~' PRIME '=' NAME '*' DEL2 '(' NAME ')' '+' NAME {partial_eqn($2, $4, $8, $11);} | '~' DEL NAME '[' firstlast ']' '=' expr {partial_bndry(0, $3, $5, $8, lastok);} | '~' NAME '[' firstlast ']' '=' expr {partial_bndry(2, $2, $4, $7, lastok);} ; firstlast: FIRST | LAST ; functableblk: FUNCTION_TABLE NAME '(' arglist ')' units {Item *b1, *b2; Symbol* s = SYM($2); s->varnum = argcnt_; b1 = insertstr($5->next, "{\n"); b2 = insertstr(b1->next, "}\n"); #define GLOBFUNCT 1 #if GLOBFUNCT && NMODL replacstr($1, "\ndouble"); #else replacstr($1, "\nstatic double"); #endif defarg($3, $5); movelist($1, b2, procfunc); if (SYM($2)->subtype & FUNCT) { diag(SYM($2)->name, " declared as FUNCTION twice"); } SYM($2)->subtype |= FUNCT; SYM($2)->usage |= FUNCT; #if HMODL || NMODL hocfunc(s, $3, $5); #endif function_table(s, $3, $5, b1, b2); poplocal(); } ; funcblk: FUNCTION1 NAME '(' arglist ')' units {IGNORE(copylocal(SYM($2)));} stmtlist '}' /* boilerplate added to form double function(){...} Note all arguments have prefix _l */ { Symbol *s = SYM($2); s->varnum = argcnt_; table_massage(table_list, $1, $2, $4); freelist(&table_list); #if GLOBFUNCT && NMODL replacstr($1, "\ndouble"); #else replacstr($1, "\nstatic double"); #endif defarg($3, $5); Sprintf(buf, "double _l%s;\n", s->name); Insertstr($8->next, buf); Sprintf(buf, "\nreturn _l%s;\n", s->name); Insertstr($9, buf); movelist($1, $9, procfunc); if (SYM($2)->subtype & FUNCT) { diag(SYM($2)->name, " declared as FUNCTION twice"); } SYM($2)->subtype |= FUNCT; SYM($2)->usage |= FUNCT; #if HMODL || NMODL hocfunc(s, $3, $5); #endif poplocal(); freelist(&$4);} ; arglist: /*nothing*/ {pushlocal(); $$ = LIST0; argcnt_ = 0;} | {pushlocal();} arglist1 {$$ = $2;} ; arglist1: name units {SYM($1) = copylocal(SYM($1)); argcnt_ = 1; $$ = newlist(); Lappendsym($$, SYM($1)); } | arglist1 ',' name units {SYM($3) = copylocal(SYM($3)); Lappendsym($$, SYM($3)); ++argcnt_; } ; procedblk: PROCEDURE NAME '(' arglist ')' units stmtlist '}' {Symbol *s = SYM($2); s->u.i = 0; /* avoid objectcenter warning if solved */ s->varnum = argcnt_; /* allow proper number of "double" in prototype */ table_massage(table_list, $1, $2, $4); freelist(&table_list); replacstr($1, "\nstatic int "); defarg($3, $5); Insertstr($8, " return 0;"); movelist($1, $8, procfunc); if (SYM($2)->subtype & PROCED) { diag(SYM($2)->name, " declared as PROCEDURE twice"); } SYM($2)->subtype |= PROCED; SYM($2)->usage |= FUNCT; #if HMODL || NMODL hocfunc(s, $3, $5); #endif poplocal(); freelist(&$4);} ; netrecblk: NETRECEIVE '(' arglist ')' { nr_argcnt_ = argcnt_; /* add flag arg */ if ($3 == LIST0) { diag("NET_RECEIVE block"," must have at least one argument"); } Lappendsym($3, copylocal(install("flag", NAME))); } stmtlist '}' { replacstr($1, "\nvoid _net_receive"); movelist($1, $7, procfunc); #if NMODL net_receive($1, $3, $2, $4, $6, $7); #endif poplocal(); freelist(&$3); } | NETRECEIVE error { myerr("syntax: NET_RECEIVE ( weight ) {stmtlist}");} ; initstmt: INITIAL1 stmtlist '}' { check_block(NETRECEIVE, blocktype, "INITIAL"); #if NMODL net_init($1, $3); #endif } ; solveblk: SOLVE NAME ifsolerr /* no processing, merely save in solve list */ { solvequeue($2, ITEM0, blocktype, $3); } | SOLVE NAME USING METHOD ifsolerr { solvequeue($2, $4, blocktype, $5); } | SOLVE error { myerr("Illegal SOLVE statement");} ; ifsolerr: /*nothing*/ { $$ = ITEM0; } | IFERROR stmtlist '}' { $$ = $3; } ; solvefor: /*nothing*/ { if (solveforlist) { freelist(&solveforlist); } } | solvefor1 ; solvefor1: SOLVEFOR NAME { solveforlist = newlist(); Lappendsym(solveforlist, SYM($2)); delete($1); delete($2); } | solvefor1 ',' NAME { Lappendsym(solveforlist, SYM($3)); delete($2); delete($3);} | SOLVEFOR error { myerr("Syntax: SOLVEFOR name, name, ...");} ; brkptblk: BREAKPOINT stmtlist '}' /* move it all to modelfunc */ {brkpnt_exists = 1; movelist($2, $3, modelfunc);} ; terminalblk: TERMINAL stmtlist '}' {movelist($2, $3, termfunc);} ; bablk: BREAKPOINT stmtlist '}' {bablk(blocktype, BREAKPOINT, $2, $3);} | SOLVE stmtlist '}' {bablk(blocktype, SOLVE, $2, $3);} | INITIAL1 stmtlist '}' {bablk(blocktype, INITIAL1, $2, $3);} | STEP stmtlist '}' {bablk(blocktype, STEP, $2, $3);} | error {myerr("[BEFORE AFTER] [BREAKPOINT SOLVE INITIAL STEP] { stmt }");} ; watchstmt: WATCH watch1 {$$ = $2; delete($1);} | watchstmt ',' watch1 {delete($2);} | WATCH error {myerr("WATCH (expr > expr) flag");} ; watch1: '(' aexpr watchdir aexpr ')' real {watchstmt($1, $3, $5, $6, blocktype); $$=$6;} ; watchdir: GT | LT ; fornetcon: FOR_NETCONS '(' arglist ')' { if (blocktype != NETRECEIVE) { diag("\"FOR_NETCONS\" statement only allowed in NET_RECEIVE block", (char*)0); } if (argcnt_ != nr_argcnt_) { diag("FOR_NETCONS and NET_RECEIVE do not have same number of arguments", (char*)0); } } stmtlist '}' {fornetcon($1, $2, $3, $4, $6, $7); $$ = $7; } | FOR_NETCONS error { myerr("syntax: FOR_NETCONS(args,like,netreceive) { stmtlist}");} ; aexpr: varname | real units | funccall | '(' aexpr ')' {lastok = $3;} | aexpr '+' aexpr | aexpr '-' aexpr | aexpr '*' aexpr | aexpr '/' aexpr | aexpr '^' aexpr /* converted to pow() */ { $$ = insertstr($1, "pow("); replacstr($2, ","); lastok = insertstr(lastok->next, ")"); } | '-' aexpr %prec UNARYMINUS | error {myerr("Illegal expression");} ; sens: SENS senslist /* sensused flag is true */ { sensused = 1; delete($1); } |SENS error {myerr("syntax is SENS var1, var2, var3, etc");} ; senslist: varname /* put in list. Used when enclosing block is massaged */ { sensparm($1); delete($1);} | senslist ',' varname { sensparm($3); deltokens($2, $3);} ; conserve: CONSERVE {extdef2 = 0; } react '=' expr {/* react originally designed for reactions and is unchanged*/ extdef2 = 0; massageconserve($1, $4, lastok);} | CONSERVE error {myerr("Illegal CONSERVE syntax");} ; compart: COMPARTMENT NAME ',' {pushlocal(); SYM($2) = copylocal(SYM($2));} expr '{' namelist '}' {massagecompart($5, $6, $8, SYM($2)); poplocal();} | COMPARTMENT expr '{' namelist '}' {massagecompart($2, $3, $5, SYM0);} ; ldifus: LONGDIFUS NAME ',' {pushlocal(); SYM($2) = copylocal(SYM($2));} expr '{' namelist '}' {massageldifus($5, $6, $8, SYM($2)); poplocal();} | LONGDIFUS expr '{' namelist '}' {massageldifus($2, $3, $5, SYM0);} ; namelist: NAME | namelist NAME ; kineticblk: KINETIC NAME solvefor stmtlist '}' /* put all reactions in a list for processing when relevant SOLVE is processed */ {massagekinetic($1, $2, $4, $5, sensused); lexcontext = 0; sensused = 0; } ; reaction: REACTION react REACT1 {leftreact();} react '(' expr ',' expr ')' {massagereaction($1,$3,$6,$8,$10);} | REACTION react LT LT '(' expr ')' {flux($1, $3, $7);} | REACTION react '-' GT '(' expr ')' {flux($1, $3, $7);} | REACTION error {myerr("Illegal reaction syntax");} ; react: varname {reactname($1, lastok, ITEM0);} |integer varname {reactname($2, lastok, $1);} |react '+' varname {reactname($3, lastok, ITEM0);} |react '+' integer varname {reactname($4, lastok, $3);} ; lagstmt: LAG name BY NAME {lag_stmt($1, blocktype);} | LAG error {myerr("Lag syntax is: LAG name BY const");} ; queuestmt: PUTQ name {queue_stmt($1, $2);} | GETQ name {queue_stmt($1, $2);} ; matchblk: MATCH {checkmatch(blocktype);} '{' matchlist '}' {deltokens($1, $5);} ; matchlist: match | matchlist match ; match: name {matchinitial($1);} | matchname '(' expr ')' '=' expr { matchbound($1, $2, $4, $6, lastok, matchindex); if (matchindex) { poplocal(); matchindex = SYM0; } } | error {myerr("MATCH syntax is state0 or state(expr)=expr or\ state[i](expr(i)) = expr(i)");} ; matchname: name {matchindex = SYM0;} | name '[' NAME ']' { pushlocal(); matchindex = copylocal(SYM($3)); } ; unitblk: UNITS '{' unitbody '}' { deltokens($1,$4);} ; unitbody: /*nothing*/ {modl_units();} | unitbody unitdef | unitbody factordef ; unitdef: unit '=' unit {install_units($1, $3);} | unit error {myerr("Unit definition syntax: (units) = (units)");} ; factordef: NAME '=' real unit { SYM($1)->subtype |= nmodlCONST; Lappendstr(units_def_for_acc, SYM($1)->name); Sprintf(buf, "\ndouble %s = %s;\n" "#pragma acc declare copyin(%s)\n" , SYM($1)->name, STR($3), SYM($1)->name); Lappendstr(firstlist, buf); } | NAME '=' unit unit { Lappendstr(units_def_for_acc, SYM($1)->name); SYM($1)->subtype |= nmodlCONST; nrnunit_dynamic_str(buf, SYM($1)->name, $3, $4); Lappendstr(firstlist, buf); Sprintf(buf, "#pragma acc declare copyin(%s)\n", SYM($1)->name); Lappendstr(firstlist, buf); } | NAME '=' unit '-' GT unit { Lappendstr(units_def_for_acc, SYM($1)->name); SYM($1)->subtype |= nmodlCONST; nrnunit_dynamic_str(buf, SYM($1)->name, $3, $6); Lappendstr(firstlist, buf); Sprintf(buf, "#pragma acc declare copyin(%s)\n", SYM($1)->name); Lappendstr(firstlist, buf); } | error {myerr("Unit factor syntax: examples:\n\ foot2inch = (foot) -> (inch)\n\ F = 96520 (coulomb)\n\ R = (k-mole) (joule/degC)"); } ; constblk: CONSTANT '{' conststmt '}' ; conststmt: /*nothing*/ | conststmt NAME '=' number units { SYM($2)->subtype |= nmodlCONST; Sprintf(buf, "static double %s = %s;\n", SYM($2)->name, STR($4)); Lappendstr(firstlist, buf); } ; tablestmt: TABLE tablst dependlst FROM expr TO expr WITH INTEGER { Item *q; if (table_list) { diag("only one TABLE per function", (char *)0); } table_list = newlist(); Lappendlst(table_list, $2); q = lappendlst(table_list, newlist()); movelist($4->next, $6->prev, LST(q)); q = lappendlst(table_list, newlist()); movelist($6->next, $8->prev, LST(q)); Lappendstr(table_list, STR($9)); Lappendlst(table_list, $3); deltokens($1, $9); } | TABLE error { myerr("syntax: TABLE [list] [DEPEND list] FROM expr TO expr WITH integer");} ; tablst: /*Nothing*/ {$$ = LIST0;} | tablst1 ; tablst1: Name {$$ = newlist(); Lappendsym($$, SYM($1));} | tablst1 ',' Name { Lappendsym($1, SYM($3));} ; dependlst: /*NOTHING*/ {$$ = LIST0;} | DEPEND tablst1 {$$ = $2;} ; neuronblk: NEURON '{' nrnstmt '}' { deltokens($1,$4);} ; nrnstmt: /*nothing*/ | nrnstmt SUFFIX NAME { nrn_list($2, $3);} | nrnstmt nrnuse | nrnstmt NONSPECIFIC nrnlist { nrn_list($2,$3);} | nrnstmt ELECTRODE_CURRENT nrnlist { nrn_list($2,$3);} | nrnstmt SECTION nrnlist { nrn_list($2, $3);} | nrnstmt RANGE nrnlist { nrn_list($2, $3);} | nrnstmt GLOBAL nrnlist { nrn_list($2, $3);} | nrnstmt POINTER nrnlist { nrn_list($2, $3);} | nrnstmt BBCOREPOINTER nrnlist { nrn_list($2, $3);} | nrnstmt EXTERNAL nrnlist { nrn_list($2, $3);} | nrnstmt THREADSAFE optnrnlist { threadsafe_seen($2, $3); } ; nrnuse: USEION NAME READ nrnlist valence {nrn_use($2, $4, ITEM0, $5);} |USEION NAME WRITE nrnlist valence {nrn_use($2, ITEM0, $4, $5);} |USEION NAME READ nrnlist WRITE nrnlist valence {nrn_use($2, $4, $6, $7);} |USEION error {myerr("syntax is: USEION ion READ list WRITE list");} ; nrnlist: NAME | nrnlist ',' NAME { delete($2); $$ = $3;} | error {myerr("syntax is: keyword name , name, ..., name");} ; optnrnlist: /*nothing*/ {$$ = NULL;} | nrnlist ; valence: /*nothing*/ {$$ = ITEM0;} | VALENCE real {$$ = $2;} | VALENCE '-' real /* replace the string with -string and discard '-'*/ { Sprintf(buf, "-%s", STR($3)); STR($3) = stralloc(buf, STR($3)); $$ = $3; delete($2); lastok = $3; } ; %% void yyerror(s) /* called for yacc syntax error */ char *s; { Fprintf(stderr, "%s:\n ", s); } #if !NMODL void nrn_list(q1, q2) Item *q1, *q2; { /*ARGSUSED*/ } void nrn_use(q1, q2, q3, q4) Item *q1, *q2, *q3, *q4; { /*ARGSUSED*/ } #endif mod2c-8.2.2/src/mod2c_core/partial.c000066400000000000000000000215621425457616700171610ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/partial.c,v 4.1 1997/08/30 20:45:33 hines Exp */ /* partial.c,v * Revision 4.1 1997/08/30 20:45:33 hines * cvs problem with branches. Latest nmodl stuff should now be a top level * * Revision 4.0.1.1 1997/08/08 17:24:00 hines * nocmodl version 4.0.1 * * Revision 4.0 1997/08/08 17:06:28 hines * proper nocmodl version number * * Revision 1.1.1.1 1994/10/12 17:21:37 hines * NEURON 3.0 distribution * * Revision 9.76 90/12/07 09:27:23 hines * new list structure that uses unions instead of void *element * * Revision 9.67 90/11/27 12:10:07 hines * bug in bnd introduced by change to partial * * Revision 9.66 90/11/27 10:47:26 hines * allow multiple partial equations within a partial block * * Revision 9.58 90/11/20 17:24:15 hines * CONSTANT changed to PARAMETER * CONSTANT now refers to variables that don't get put in .var file * * Revision 9.20 90/08/15 15:16:16 hines * need to pass error value from crank back through the * block called by SOLVE. * * Revision 8.1 90/01/16 11:06:14 mlh * error checking and cleanup after error and call to abort_run() * * Revision 8.0 89/09/22 17:26:54 nfh * Freezing * * Revision 7.0 89/08/30 13:32:29 nfh * Rev 7 is now Experimental; Rev 6 is Testing * * Revision 6.0 89/08/14 16:27:10 nfh * Rev 6.0 is latest of 4.x; now the Experimental version * * Revision 4.1 89/07/27 13:27:30 mlh * crank calling sequence sends indepsym as a sentinal value * ugh! * * Revision 4.0 89/07/24 17:03:40 nfh * Freezing rev 3. Rev 4 is now Experimental * * Revision 3.3 89/07/18 11:55:16 mlh * first_time removed and MODEL_LEVEL used for declaration precedence * * Revision 1.4 89/07/18 11:22:16 mlh * eliminate first_time, etc. * * Revision 1.3 89/07/11 16:51:58 mlh * remove p array from calling sequence of crank * * Revision 1.2 89/07/07 08:55:01 mlh * START field in INDEPENDENT block * SWEEP keyword replaces SCOP in INDEPENDENT block * FIRST and LAST keywords in PARTIAL block for boundaries rplace index * y'0 etc. allowed for constants * * Revision 1.1 89/07/06 14:50:25 mlh * Initial revision * */ #include "modl.h" #include "parse1.h" #include "symbol.h" extern Symbol *indepsym; /* for partial block communication with solve */ static Symbol *pv[4]; /* DV, F, V, G */ static Item *partialcolon; static List *parinfo; /* DV, F, V, G, ~ with ident */ void solv_partial(qsol, fun) Item *qsol; Symbol *fun; { int i, ident; Item *q; Symbol *dspace; if ((dspace = lookup("delta_x")) == SYM0) { dspace = install("delta_x", NAME); parminstall(dspace, "1", ""); } Sprintf(buf, "%s();\n", fun->name); replacstr(qsol, buf); save_dt(partialcolon); ITERATE(q, parinfo) { for (i=0; i<4; i++) { pv[i] = SYM(q); q = q->next; } partialcolon = ITM(q); ident = q->itemtype; Sprintf(buf, "if (error=crank(%d, %s, %s, %s, delta_%s, %s, %s, _pbound%d, &_parwork%d))return error;\n", pv[2]->araydim, pv[2]->name, pv[1]->name, pv[3]->name, indepsym->name, dspace->name, indepsym->name, ident, ident); replacstr(partialcolon, buf); Sprintf(buf, "static double *_pbound%d[4], _bnd%d_0, _bnd%d_N, *_parwork%d;\n", ident, ident, ident, ident); Linsertstr(procfunc, buf); } } void partial_eqn(q2, q4, q8, q11) /*V' F V G*/ Item *q2, *q4, *q8, *q11; { int i, dim; Item *q; static int ident=1; if (!parinfo) { parinfo = newlist(); } pv[0] = SYM(q2); pv[1] = SYM(q4); pv[2] = SYM(q8); pv[3] = SYM(q11); ITERATE(q, parinfo) { if (SYM(q) == SYM(q2)) { diag("Two partial equations for same state: ", SYM(q8)->name); } q = q->next->next->next->next; } Lappendsym(parinfo, SYM(q2)); Lappendsym(parinfo, SYM(q4)); Lappendsym(parinfo, SYM(q8)); Lappendsym(parinfo, SYM(q11)); q = lappendsym(parinfo, SYM0); ITM(q) = q2->prev; q->itemtype = ident++; dim = pv[2]->araydim; if (!(pv[2]->subtype & STAT)){ diag(pv[2]->name, " is not a STATE"); } if (strcmp(pv[2]->name, pv[0]->name + 1)) { diag(pv[2]->name, "' must be the time derivative"); } for (i=0; i<4; i++) { if (!(pv[i]->subtype & ARRAY) || (pv[i]->araydim != dim)) { diag(pv[i]->name, " dimension differs from STATE var"); } } replacstr(q2->prev, "\n/*where partial call goes*/\n"); partialcolon = q2->prev; deltokens(q2, q11); } static List *bndinfo; /* symbol, expression list with itemtype 0-3 */ static List *bnd[4]; /* for each condition consisting of symbol, list of tokens for expression in the order DEL y[0] DEL y[N] y[0] y[N]*/ void massagepartial(q1, q2, q3, q6) /*PARTIAL NAME stmtlist '}'*/ Item *q1, *q2, *q3, *q6; { int i, ident; Item *q, *qb; Symbol *s; static int seepartial = 0; if (seepartial++) { diag("Only one partial block currently allowed", (char *)0); } if (!pv[0]) { diag( "within the PARTIAL block must occur at least one equation with the syntax ---\n", "~ V' = F*DEL2(V) + G\n"); } if (!bndinfo) { bndinfo = newlist(); } ITERATE(q, parinfo) { for (i=0; i<4; i++) { pv[i] = SYM(q); q = q->next; bnd[i] = (List *)0; } partialcolon = ITM(q); ident = q->itemtype; /*look through bndinfo list to reconstruct bnd*/ ITERATE(qb, bndinfo) { s = SYM(qb); qb = qb->next; if (s == pv[2]) { if (bnd[qb->itemtype]) { diag("Duplicate boundary condition for ", s->name); } bnd[qb->itemtype] = LST(qb); qb->itemtype = -1; /* mark used */ } } /* ensure that there is one condition on each side */ for (i=0; i<2; i++) { if (bnd[i]) { /* Neumann */ if (bnd[i+2]) { /* and also dirichlet */ diag("Neumann and Dirichlet conditions", " specified on same side"); } } else { /* Neumann not specified */ if (!bnd[i+2]) { /* neither is dirichlet */ /* then default Neumann = 0 */ bnd[i] = newlist(); Lappendstr(bnd[i], "0"); } } } /* place the boundary conditions before the call to crank */ /* and set up the pointers */ for (i=0; i<4; i++) { if (bnd[i]) { if (i%2) { Sprintf(buf, "_bnd%d_N = ", ident); Insertstr(partialcolon, buf); Sprintf(buf, "_pbound%d[%d] = &_bnd%d_N;\n", ident, i, ident); }else{ Sprintf(buf, "_bnd%d_0 = ", ident); Insertstr(partialcolon, buf); Sprintf(buf, "_pbound%d[%d] = &_bnd%d_0;\n", ident, i, ident); } Lappendstr(initlist, buf); move(bnd[i]->next, bnd[i]->prev, partialcolon); Insertstr(partialcolon, ";\n"); } } } /* check that all boundary conditions have been used */ ITERATE(qb, bndinfo) { s = SYM(qb); qb = qb->next; if (qb->itemtype != -1) { diag("Boundary condition: No partial equation for ", s->name); } } replacstr(q1, "int"); Insertstr(q3, "()\n"); SYM(q2)->subtype |= PARF; SYM(q2)->u.i = 0; /* not used: but see listnum in solvhandler */ Insertstr(q6, "return 0;\n"); movelist(q1, q6, procfunc); } /* ~ optionalDEL var[index] = expr */ /* type 0 Dirichlet (no DEL), type 1 Neumann (with DEL) */ void partial_bndry(type, qvar, qfirstlast, qexpr, qlast) int type; Item *qvar, *qfirstlast, *qexpr, *qlast; { int indx; Item *q; List *l; if (!bndinfo) { bndinfo = newlist(); } if (SYM(qfirstlast)->type == FIRST) { indx = type; }else{ indx = type + 1; } Lappendsym(bndinfo, SYM(qvar)); q = lappendsym(bndinfo, SYM0); q->itemtype = indx; l = newlist(); LST(q) = l; if (indx < 2) { /* ~ DEL y [N] = */ deltokens(qvar->prev->prev, qexpr->prev); }else{ /* ~ ... = */ deltokens(qvar->prev, qexpr->prev); } movelist(qexpr, qlast, l); } mod2c-8.2.2/src/mod2c_core/portability.h000066400000000000000000000004001425457616700200600ustar00rootroot00000000000000#ifndef mod2c_portability_h #define mod2c_portability_h #ifdef MINGW // mkdir doesn't accept permission parameter on mingw #define mkdir(directory, permission) mkdir(directory) // use strchr instead of index on mingw #define index strchr #endif #endif mod2c-8.2.2/src/mod2c_core/sens.c000066400000000000000000000317631425457616700165010ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/sens.c,v 4.2 1997/11/28 15:11:43 hines Exp */ /* sens.c,v * Revision 4.2 1997/11/28 15:11:43 hines * absolute tolerance for CVODE on a per state basis. * Interface is a spec of absolute tolerance within a .mod file for the * declaration of a STATE as in * state (units) * Within nrniv, one specifies tolerance via * tol = cvode.abstol(&var, tolerance) where var is any variable whose address * can be taken (although only STATEs make use of a tolerance). * The address aspect of the above is misleading since tolerances are the * same for any single name, eg cvode.abstol(&v(.5)) changes tolerances for * ALL membrane potentials globally. The only purpose of the address is * to unambiguously identify the Symbol for the name. Perhaps string spec * such as "TrigKSyn.G" will be incorporated in the future. * when an absolute tolerance is changed, cvode will re-initialize the * tolerances next time Cvode.re_init is called. The tolerance actually * used for a STATE is the minimum between the value specified in the second * arg of cvode.accuracy and the tolerance stored in the Symbol. * * Revision 4.1 1997/08/30 20:45:34 hines * cvs problem with branches. Latest nmodl stuff should now be a top level * * Revision 4.0.1.1 1997/08/08 17:24:01 hines * nocmodl version 4.0.1 * * Revision 4.0 1997/08/08 17:06:28 hines * proper nocmodl version number * * Revision 1.2 1995/09/05 17:57:58 hines * allow domain limit in parameter spec. the syntax is of the form * name '=' number units '[' number ',' number ']' * The brackets may be changed to <...> if the syntax for arrays is ambiguous * * Revision 1.1.1.1 1994/10/12 17:21:37 hines * NEURON 3.0 distribution * * Revision 9.76 90/12/07 09:27:25 hines * new list structure that uses unions instead of void *element * * Revision 9.58 90/11/20 17:24:17 hines * CONSTANT changed to PARAMETER * CONSTANT now refers to variables that don't get put in .var file * * Revision 9.45 90/10/30 13:56:56 hines * derivative blocks (this impacts kinetic and sens as well) now return * _reset which can be set with RESET statement. _reset is static in the * file and set to 0 on entry to a derivative or kinetic block. * * Revision 9.32 90/10/08 14:12:55 hines * index vector instead of pointer vector for slist and dlist * * Revision 8.2 90/02/07 10:23:23 mlh * It is important that blocks for derivative and sensitivity also * be declared static before their possible use as arguments to other * functions and that their body also be static to avoid multiple * declaration errors. * * Revision 8.1 90/01/16 11:06:16 mlh * error checking and cleanup after error and call to abort_run() * * Revision 8.0 89/09/22 17:26:57 nfh * Freezing * * Revision 7.0 89/08/30 13:32:33 nfh * Rev 7 is now Experimental; Rev 6 is Testing * * Revision 6.0 89/08/14 16:27:13 nfh * Rev 6.0 is latest of 4.x; now the Experimental version * * Revision 4.1 89/08/07 15:35:26 mlh * freelist now takes pointer to list pointer and 0's the list pointer. * Not doing this is a bug for multiple sens blocks, etc. * * Revision 4.0 89/07/24 17:03:43 nfh * Freezing rev 3. Rev 4 is now Experimental * * Revision 3.2 89/07/18 11:55:19 mlh * first_time removed and MODEL_LEVEL used for declaration precedence * * Revision 1.2 89/07/18 11:22:19 mlh * eliminate first_time, etc. * * Revision 1.1 89/07/06 14:50:34 mlh * Initial revision * */ #include "modl.h" #include "parse1.h" static List *sensinfo; /* list of pairs: first is the block symbol where the SENS statement appeared. The second is a list of statements which goes after the SOLVE statement. Used for NONLINEAR blocks. So far sensmassage gets control when massageblock is almost finished */ static List *statelist; static List *parmlist; extern Symbol *indepsym; int sens_parm = 0; void sensparm(qparm) Item *qparm; { if (!parmlist) parmlist = newlist(); Lappendsym(parmlist, SYM(qparm)); sens_parm++; } void add_sens_statelist(s) Symbol *s; { if (!statelist) statelist = newlist(); Lappendsym(statelist, s); } void sensmassage(type, qfun, fn) int type; Item *qfun; int fn; { /*qfun is the list symbol for the name of the derivative block. It has a count of the number of state variables used. A copy of this symbol is made but with the name S_name and qfun is made to point to the new symbol The old function name is then the name of a new created function which contains the calls to trajecsens followed by a call to S_name to compute the Note that trajecsens itself contains calls to S_name. qfun->sym->used is then multiplied by the (1 + #sens parms used) so that the solve code doesn't need to be changed. The slist needs to be augmented and that is done here also. However since it is declared in solve.c it is necessary to access the number of parameters being used. */ /* extending to nonlinear blocks. Differences: Number of states remains the same. Statements built here but saved for output when SOLVE is translated. No derivative variables constructed. However, the full dlist is constructed since we need the last part for use by EM variables This has gotten much more difficult to understand since the nonlinear method is merged into the code to take advantage of common code. It would be conceptually simpler to merely repeat the whole process in a separate file*/ /* extending to linear blocks. Same as nonlinear except that there is a linearsens call and we must be sure to keep proper state order */ int nstate, i, j, newjac; char sname[100], dname[100]; Item *q, *q1; List *senstmt; /* nonlinear sens statements (saved in sensinfo) */ Symbol *oldfun, *newfun, *s; oldfun = SYM(qfun); Sprintf(buf, "S_%s", oldfun->name); if (lookup(buf)) { diag(buf, " is user defined and cant be used for SENS"); } /*this is a time bomb*/ newfun = install(buf, oldfun->type); newfun->subtype = oldfun->subtype; newfun->u.i = oldfun->u.i; /*the listnum*/ newfun->used = oldfun->used; /*number of states*/ nstate = oldfun->used; if (type == DERIVATIVE) { oldfun->used *= (1 + sens_parm); } /* even derivatives need sensinfo since envelope statements go after the SOLVE for statement */ if (!sensinfo) { sensinfo = newlist(); } Lappendsym(sensinfo, oldfun); /* newton will call oldfun which will merely call newfun */ q = lappendsym(sensinfo, SYM0); /* the second element is a list of statements to be constructed below */ senstmt = newlist(); LST(q) = senstmt; SYM(qfun) = newfun; /* the derivative equations alone are now called newfun->name; oldfun will contain the trajecsens calls */ /* build the oldfun function */ /* In the nonlinear case all statements except call to newfun get sent to senstmt */ /* in the derivative case envelope statements get sent to senstmt */ Sprintf(buf, "\nstatic int %s() {\n", oldfun->name); Lappendstr(procfunc, buf); Sprintf(buf, "\nstatic int %s();\n", newfun->name); Linsertstr(procfunc, buf); newjac = 1; i=1; ITERATE(q, parmlist) { if (type == DERIVATIVE) { Sprintf(buf, "error=trajecsens(%d, _slist%d, _dlist%d,\ _p, &%s, %s, %s, %d, _slist%d+%d, _dlist%d+%d);\n if(error){abort_run(error);}\n", nstate, fn, fn, SYM(q)->name, newfun->name, indepsym->name, newjac, fn, nstate*i, fn, nstate*i); Lappendstr(procfunc, buf); }else if (type == NONLINEAR) { Sprintf(buf, "error=steadysens(%d, _slist%d, _p, &%s, %s,\ _dlist%d, %d, _slist%d+%d);\n if(error){abort_run(error);}\n", nstate, fn, SYM(q)->name, newfun->name, fn, newjac, fn, nstate*i); Lappendstr(senstmt, buf); }else if (type == LINEAR) { Sprintf(buf, "error=linearsens(%d, _slist%d, _p, &%s, %s,\ _coef%d, %d, _slist%d+%d);\n if(error){abort_run(error);}\n", nstate, fn, SYM(q)->name, newfun->name, fn, newjac, fn, nstate*i); Lappendstr(senstmt, buf); } newjac = 0; /* define S_state_parm and DS_state_parm */ ITERATE(q1, statelist) { j = SYM(q1)->varnum; Sprintf(sname, "S_%s_%s", SYM(q1)->name, SYM(q)->name); Sprintf(dname, "D%s", sname); if ((s = lookup(sname)) == SYM0) { s = install(sname, NAME); } if (SYM(q1)->subtype & ARRAY) { depinstall(1, s, SYM(q1)->araydim, "0", "1", "", ITEM0, 0, ""); }else{ depinstall(1, s, 0, "0", "1", "", ITEM0, 0, ""); } s->usage |= DEP; if (type == DERIVATIVE) { s = lookup(dname); assert (s); s->usage |= DEP; /* initialize augmented _slist and _dlist */ if (SYM(q1)->subtype & ARRAY) { Sprintf(buf, "for (_i=0;_i<%d;_i++){\ _slist%d[%d+_i] = (%s + _i) - _p; _dlist%d[%d+_i] = (%s + _i) - _p;}\n", SYM(q1)->araydim, fn, j + nstate*i, sname, fn, j + nstate*i, dname); }else{ Sprintf(buf, "_slist%d[%d] = &(%s) - _p; _dlist%d[%d] = &(%s) - _p;\n", fn, j + nstate*i, sname, fn, j + nstate*i, dname); } }else if (type == NONLINEAR || type == LINEAR) { if (SYM(q1)->subtype & ARRAY) { Sprintf(buf, "for (_i=0;_i<%d;_i++){\ _slist%d[%d+_i] = (%s + _i) - _p;}\n", SYM(q1)->araydim, fn, j + nstate*i, sname); }else{ Sprintf(buf, "_slist%d[%d] = &(%s) - _p;\n", fn, j + nstate*i, sname); } } Lappendstr(initlist, buf); } i++; } /* addition of envelope calls by modifying copy of above code create EP_state_parm, EM_state_parm using a new eplist and emlist respectively. Also create U_parm with default value of .05 if it doesn't already exist as a constant. */ Sprintf(buf, "static int _eplist%d[%d], _emlist%d[%d];\n", fn, nstate*sens_parm, fn, nstate*sens_parm); Linsertstr(procfunc, buf); i = 0; ITERATE(q, parmlist) { Sprintf(buf, "envelope(_p, _slist%d, %d, %s, U_%s,\ _slist%d+%d, _eplist%d + %d, _emlist%d + %d);\n", fn, nstate, SYM(q)->name, SYM(q)->name, fn, nstate*(1 + i), fn, nstate*i, fn, nstate*i); Lappendstr(senstmt, buf); /* define the uncertainty variables */ Sprintf(buf, "U_%s", SYM(q)->name); IGNORE(ifnew_parminstall(buf, "0.05", "", "")); /* define EP_state_parm and EM_state_parm */ ITERATE(q1, statelist) { j = SYM(q1)->varnum; Sprintf(sname, "EP_%s_%s", SYM(q1)->name, SYM(q)->name); Sprintf(dname, "EM_%s_%s", SYM(q1)->name, SYM(q)->name); if ((s = lookup(sname)) == SYM0) { s = install(sname, NAME); } if (SYM(q1)->subtype & ARRAY) { depinstall(0, s, SYM(q1)->araydim, "0", "1", "", ITEM0, 0, ""); }else{ depinstall(0, s, 0, "0", "1", "", ITEM0, 0, ""); } s->usage |= DEP; if ((s = lookup(dname)) == SYM0) { s = install(dname, NAME); } if (SYM(q1)->subtype & ARRAY) { depinstall(0, s, SYM(q1)->araydim, "0", "1", "", ITEM0, 0, ""); }else{ depinstall(0, s, 0, "0", "1", "", ITEM0, 0, ""); } s->usage |= DEP; /* initialize augmented _slist and _dlist */ if (SYM(q1)->subtype & ARRAY) { Sprintf(buf, "for (_i=0;_i<%d;_i++){\ _eplist%d[%d+_i] = (%s + _i) - _p; _emlist%d[%d+_i] = (%s + _i) - _p;}\n", SYM(q1)->araydim, fn, j + nstate*i, sname, fn, j + nstate*i, dname); }else{ Sprintf(buf, "_eplist%d[%d] = &(%s) - _p; _emlist%d[%d] = &(%s) - _p;\n", fn, j + nstate*i, sname, fn, j + nstate*i, dname); } Lappendstr(initlist, buf); } i++; } if (type == DERIVATIVE) { Sprintf(buf, "return %s();\n}\n", newfun->name); }else{ Sprintf(buf, "%s();\n}\n", newfun->name); } Lappendstr(procfunc, buf); freelist(&parmlist); freelist(&statelist); sens_parm = 0; } void sens_nonlin_out(q, fun) Item *q; Symbol *fun; { /* find fun in the sensinfo list and insert its statements before q */ Item *q1, *q2, *q3; if (!sensinfo) return; ITERATE(q1, sensinfo) { q2 = q1->next; if (SYM(q1) == fun) { ITERATE(q3, LST(q2)) { Insertstr(q, STR(q3)); } } q1 = q2; } } mod2c-8.2.2/src/mod2c_core/simultan.c000066400000000000000000000321601425457616700173550ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" #include "modl.h" #include "parse1.h" #include "symbol.h" extern int sens_parm; extern int numlist; static List *eqnq; static int nonlin_common(); void solv_nonlin(qsol, fun, method, numeqn, listnum) Item *qsol; Symbol *fun, *method; int numeqn, listnum; { Sprintf(buf, "%s(%d,_slist%d, _p, %s, _dlist%d);\n", method->name, numeqn, listnum, fun->name, listnum); replacstr(qsol, buf); /* if sens statement appeared in fun then the steadysens call list, built during the massagenonlin phase gets added after the call to newton */ sens_nonlin_out(qsol->next, fun); } void solv_lineq(qsol, fun, method, numeqn, listnum) Item *qsol; Symbol *fun, *method; int numeqn, listnum; { Sprintf(buf, " 0; %s();\n error = %s(%d, _coef%d, _p, _slist%d);\n", fun->name, method->name, numeqn, listnum, listnum); replacstr(qsol, buf); sens_nonlin_out(qsol->next, fun); } void eqnqueue(q1) Item *q1; { Item *lq; if (!eqnq) { eqnq = newlist(); } lq = lappendsym(eqnq, SYM0); ITM(lq) = q1; return; } static void freeqnqueue() { freelist(&eqnq); } /* args are --- nonlinblk: NONLINEAR NAME stmtlist '}' */ void massagenonlin(q1, q2, q3, q4, sensused) Item *q1, *q2, *q3, *q4; int sensused; { /* declare a special _counte variable to number the equations. before each equation we increment it by 1 during run time. This gives us a current equation number */ Symbol *nonfun; /* all this junk is still in the intoken list */ Sprintf(buf, "static void %s();\n", SYM(q2)->name); Linsertstr(procfunc, buf); replacstr(q1, "\nstatic void"); Insertstr(q3, "()\n"); Insertstr(q3->next, " int _counte = -1;\n"); nonfun = SYM(q2); if ((nonfun->subtype) & NLINF && nonfun->u.i) { diag("NONLINEAR merging not implemented", (char *)0); } numlist++; nonfun->subtype |= NLINF; nonfun->u.i = numlist; nonfun->used = nonlin_common(q4, sensused); movelist(q1, q4, procfunc); if (sensused) { sensmassage(NONLINEAR, q2, numlist); } } static int nonlin_common(q4, sensused) /* used by massagenonlin() and mixed_eqns() */ Item *q4; int sensused; { Item *lq, *qs, *q; int i, counts = 0, counte = 0, using_array; Symbol *s; using_array=0; counts =0; SYMITER_STAT { if (s->used) { if (s->subtype & ARRAY) {int dim = s->araydim; counts += dim; }else{ counts++; } } } Sprintf(buf, "_slist%d = (int*)malloc(sizeof(int)*%d);\n", numlist, counts); Lappendstr(initlist, buf); counts = 0; SYMITER_STAT { if (s->used) { s->varnum = counts; #if CVODE slist_data(s, counts, numlist); #endif if (s->subtype & ARRAY) {int dim = s->araydim; using_array=1; Sprintf(buf, "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = (%s + _i) - _p;}\n" ,dim, numlist , counts, s->name); counts += dim; }else{ Sprintf(buf, "_slist%d[%d] = &(%s) - _p;\n", numlist, counts, s->name); counts++; } Lappendstr(initlist, buf); s->used = 0; if (sensused) { add_sens_statelist(s); } } } Sprintf(buf, "#pragma acc enter data copyin(_slist%d[0:%d])\n\n", numlist, counts); Lappendstr(initlist, buf); ITERATE(lq, eqnq) { char *eqtype = SYM(ITM(lq))->name; if (strcmp(eqtype, "~+") == 0) { /* add equation to previous */ if (counte == -1) { diag("no previous equation for adding terms", (char *)0); } Sprintf(buf, "_dlist%d[_counte] +=", numlist); } else if (eqtype[0] == 'D') { /* derivative equations using implicit method */ int count_deriv = SYM(ITM(lq))->araydim; Sprintf(buf, "_dlist%d[(++_counte)*_STRIDE] =", numlist); counte += count_deriv; }else{ Sprintf(buf, "_dlist%d[(++_counte)*_STRIDE] =", numlist); counte++; } replacstr(ITM(lq), buf); } if (!using_array) { if(counte != counts) { Sprintf(buf ,"Number of equations, %d, does not equal number, %d", counte, counts); diag(buf, " of states used"); } } else { #if 1 /* can give message when running */ Sprintf(buf, "if(_counte != %d) printf( \"Number of equations, %%d,\ does not equal number of states, %d\", _counte + 1);\n", counts-1, counts); Insertstr(q4, buf); #endif } if (counte == 0) { diag("NONLINEAR contains no equations", (char *)0); } freeqnqueue(); Sprintf(buf, ", _slist%d[0:%d]", numlist, counts*(1 + sens_parm)); Lappendstr(acc_present_list, buf); Sprintf(buf, "static int _slist%d[%d]; static double _dlist%d[%d];\n", numlist, counts*(1 + sens_parm), numlist, counts); q = linsertstr(procfunc, buf); Sprintf(buf, "\n#define _slist%d _slist%d%s\n" "int* _slist%d;\n" "#pragma acc declare create(_slist%d)\n" , numlist, numlist, suffix, numlist, numlist); vectorize_substitute(q, buf); return counts; } Item *mixed_eqns(q2, q3, q4) /* name, '{', '}' */ Item *q2, *q3, *q4; { int counts; Item *qret; Item* q; if (!eqnq) { return ITEM0; /* no nonlinear algebraic equations */ } /* makes use of old massagenonlin split into the guts and the header stuff */ numlist++; counts = nonlin_common(q4, 0); q = insertstr(q3, "{\n"); sprintf(buf, "{ double* _savstate%d = (double*)_thread[_dith%d]._pval;\n\ double* _dlist%d = (double*)(_thread[_dith%d]._pval) + (%d*_cntml_padded);\n", numlist-1, numlist-1, numlist, numlist-1, counts); vectorize_substitute(q, buf); Sprintf(buf, "error = newton(%d,_slist%d, _p, _newton_%s%s, _dlist%d);\n", counts, numlist, SYM(q2)->name, suffix, numlist); qret = insertstr(q3, buf); Sprintf(buf, "_reset = nrn_newton_thread(static_cast(_newtonspace%d), %d, _slist%d, _newton_%s%s{}, _dlist%d, _threadargs_);\n" , numlist-1, counts, numlist, SYM(q2)->name, suffix, numlist); vectorize_substitute(qret, buf); Insertstr(q3, "/*if(_reset) {abort_run(_reset);}*/ }\n"); Sprintf(buf, "\nstruct _newton_%s%s {\n int operator()(_threadargsproto_) const;\n};\n" , SYM(q2)->name, suffix); Linsertstr(procfunc, buf); Sprintf(buf, "\n" "/* _derivimplicit_ %s %s */\n" "#ifndef INSIDE_NMODL\n" "#define INSIDE_NMODL\n" "#endif\n" , SYM(q2)->name, suffix); Linsertstr(procfunc, buf); Sprintf(buf, "\n return _reset;\n}\n\nint _newton_%s%s::operator()(_threadargsproto_) const {\n int _reset=0;\n", SYM(q2)->name, suffix); Insertstr(q3, buf); q = insertstr(q3, "{ int _counte = -1;\n"); sprintf(buf, "{ double* _savstate%d = (double*)_thread[_dith%d]._pval;\n\ double* _dlist%d = (double*)(_thread[_dith%d]._pval) + (%d*_cntml_padded);\n int _counte = -1;\n", numlist-1, numlist-1, numlist, numlist-1, counts); vectorize_substitute(q, buf); Insertstr(q4, "\n }"); return qret; } /* linear simultaneous equations */ /* declare a _counte variable to dynamically contain the current equation number. This is necessary to allow use of state vectors. It is no longer necessary to count equations here but we do it anyway in case of future move to named equations. It is this change which requires a varnum field in Symbols for states since the arraydim field cannot be messed with anymore. */ static int nlineq = -1; /* actually the current index of the equation */ /* is only good if there are no arrays */ static int using_array; /* 1 if vector state in equations */ static int nstate = 0; static Symbol *linblk; static Symbol *statsym; void init_linblk(q) /* NAME */ Item *q; { using_array = 0; nlineq = -1; nstate = 0; linblk = SYM(q); numlist++; } void init_lineq(q1) /* the colon */ Item *q1; { if (strcmp(SYM(q1)->name, "~+") == 0) { replacstr(q1, ""); }else { nlineq++; /* current index will start at 0 */ replacstr(q1, " ++_counte;\n"); } } static char *indexstr; /* set in lin_state_term, used in linterm */ void lin_state_term(q1, q2) /* term last*/ Item *q1, *q2; { char *qconcat(); /* but puts extra ) at end */ statsym = SYM(q1); replacstr(q1, "1.0"); if (statsym->subtype & ARRAY) { indexstr = qconcat(q1->next->next, q2->prev); deltokens(q1->next, q2->prev); /*can't erase lastok*/ replacstr(q2, ""); } if (statsym->used == 1) { statsym->varnum = nstate; if (statsym->subtype & ARRAY) {int dim = statsym->araydim; using_array=1; Sprintf(buf, "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = (%s + _i) - _p;}\n" ,dim, numlist , nstate, statsym->name); nstate += dim; }else{ Sprintf(buf, "_slist%d[%d] = &(%s) - _p;\n", numlist, nstate, statsym->name); nstate++; } Lappendstr(initlist, buf); } } void linterm(q1, q2, pstate, sign) /*primary, last ,, */ Item *q1, *q2; int pstate, sign; { char *signstr; if (pstate == 0) { sign *= -1; } if (sign == -1) { signstr = " -= "; } else { signstr = " += "; } if (pstate == 1) { if (statsym->subtype & ARRAY) { Sprintf(buf, "_coef%d[_counte][%d + %s]%s", numlist, statsym->varnum, indexstr, signstr); } else { Sprintf(buf, "_coef%d[_counte][%d]%s", numlist, statsym->varnum, signstr); } Insertstr(q1, buf); } else if (pstate == 0) { Sprintf(buf, "_RHS%d(_counte)%s", numlist, signstr); Insertstr(q1, buf); }else{ diag("more than one state in preceding term", (char *)0); } Insertstr(q2->next, ";\n"); } void massage_linblk(q1, q2, q3, q4, sensused) /* LINEAR NAME stmtlist '}' */ Item *q1, *q2, *q3, *q4; int sensused; { Item *qs; Symbol *s; int i; #if LINT assert(q2); #endif if (++nlineq == 0) { diag(linblk->name, " has no equations"); } Sprintf(buf, "static void %s();\n", SYM(q2)->name); Linsertstr(procfunc, buf); replacstr(q1, "\nstatic void"); Insertstr(q3, "()\n"); Insertstr(q3->next, " int _counte = -1;\n"); linblk->subtype |= LINF; linblk->u.i = numlist; SYMITER(NAME){ if ((s->subtype &STAT) && s->used) { if (sensused) { add_sens_statelist(s); } s->used = 0; } } if (!using_array) { if (nlineq != nstate) { Sprintf(buf,"Number states, %d, unequal to equations, %d in ", nstate, nlineq); diag(buf, linblk->name); } } else { #if 1 /* can give message when running */ Sprintf(buf, "if(_counte != %d) printf( \"Number of equations, %%d,\ does not equal number of states, %d\", _counte + 1);\n", nstate-1, nstate); Insertstr(q4, buf); #endif } linblk->used = nstate; Sprintf(buf, "static int _slist%d[%d];static double **_coef%d;\n", numlist, nstate*(1 + sens_parm), numlist); Linsertstr(procfunc, buf); Sprintf(buf, "\n#define _RHS%d(arg) _coef%d[arg][%d]\n", numlist, numlist, nstate); Linsertstr(procfunc, buf); Sprintf(buf, "if (_first) _coef%d = makematrix(%d, %d);\n", numlist, nstate, nstate+1); Lappendstr(initlist, buf); Sprintf(buf, "zero_matrix(_coef%d, %d, %d);\n{\n", numlist, nstate, nstate+1); Insertstr(q3->next, buf); Insertstr(q4, "\n}\n"); movelist(q1, q4, procfunc); if (sensused) { sensmassage(LINEAR, q2, numlist); } nstate = 0; nlineq = 0; } /* It is sometimes convenient to not use some states in solving equations. We use the SOLVEFOR statement to list the states in LINEAR, NONLINEAR, and KINETIC blocks that are to be treated as states in fact. States not listed are treated in that block as assigned variables. If the SOLVEFOR statement is absent all states are assumed to be in the list. Syntax is: blocktype blockname [SOLVEFOR name, name, ...] { statement } The implementation uses the varname: production that marks the state->used record. The old if statement was if (inequation && (SYM($1)->subtype & STAT)) { then mark states} now we add && in_solvefor() to indicate that it Really should be marked. The hope is that no further change to diagnostics for LINEAR or NONLINEAR will be required. Some more work on KINETIC is required since the checking on whether a name is a STAT is done much later. The solveforlist is freed at the end of each block. */ List *solveforlist = (List *)0; int in_solvefor(s) Symbol *s; { Item *q; if (!solveforlist) { return 1; } ITERATE(q, solveforlist) { if (s == SYM(q)) { return 1; } } return 0; } mod2c-8.2.2/src/mod2c_core/solve.c000066400000000000000000000405411425457616700166530ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/nmodl/solve.c,v 4.4 1998/08/20 21:07:34 hines Exp */ #include "modl.h" #include "parse1.h" #include "symbol.h" /* make it an error if 2 solve statements are called on a single call to model() */ extern List *indeplist; Symbol *deltaindep = SYM0; extern Symbol *indepsym; extern char* current_line(); extern List *massage_list_; #if NMODL extern List *nrnstate; #if VECTORIZE extern int vectorize; extern char* cray_pragma(); #endif #endif #if CVODE Item* cvode_cnexp_solve; Symbol* cvode_nrn_cur_solve_; Symbol* cvode_nrn_current_solve_; #endif static void whileloop(); static void check_ss_consist(); /* Need list of solve statements. We impress the general list structure to handle it. The element is a pointer to an item which is the first item in the statement sequence in another list. */ static List *solvq; /* list of the solve statement locations */ int numlist = 0; /* number of slist's */ void solvequeue(q1, q2, blocktype, qerr) /*solve NAME=q1 [using METHOD=q2]*/ /* q2 = 0 means method wasn't there */ /* qerr in ITEM0 or else the closing brace of an IFERROR stmt */ Item *q1, *q2, *qerr; int blocktype; { /* the solvq list is organized in groups of an item element followed by the method symbol( null if default to be used) */ /* The itemtype field of the first is used to carry the blocktype*/ /* SOLVE and METHOD method are deleted */ /* The list now consists of triples in which the third element is a list containing the complete IFERROR statement. */ Item *lq, *qtemp; List *errstmt; if (!solvq) { solvq = newlist(); } #if NMODL /* if the blocktype is equation then move the solve statement to the nrnstate function. Everything else stays in the model function to be used as the nrncurrent function */ if (blocktype == BREAKPOINT) { if (!nrnstate) { nrnstate = newlist(); } Lappendstr(nrnstate, "{"); if (qerr) { movelist(q1->prev, qerr, nrnstate); }else if (q2) { movelist(q1->prev, q2, nrnstate); }else{ movelist(q1->prev, q1, nrnstate); } Lappendstr(nrnstate, "}"); } /* verify that the block defintion for this SOLVE has not yet been seen */ if (massage_list_) ITERATE(lq, massage_list_) { if (strcmp(SYM(lq)->name, SYM(q1)->name) == 0) { diag("The SOLVE statement must be before the DERIVATIVE block for ", SYM(lq)->name); } } #endif lq = lappendsym(solvq, SYM0); ITM(lq) = q1; lq->itemtype = blocktype; /* handle STEADYSTATE option */ if (q1->next->itemtype == SYMBOL && strcmp("STEADYSTATE", SYM(q1->next)->name) == 0) { lq->itemtype = -blocktype; /* gets put back below */ } if (q2) { qtemp = q2->next; /* The IFERROR location */ Lappendsym(solvq, SYM(q2)); if (strcmp(SYM(q2)->name, "derivimplicit") == 0) { add_deriv_imp_list(SYM(q1)->name); add_deriv_imp_really(SYM(q1)->name); } if (strcmp(SYM(q2)->name, "cnexp") == 0) { SYM(q2)->name = stralloc("derivimplicit", SYM(q2)->name); add_deriv_imp_list(SYM(q1)->name); #if CVODE cvode_cnexp_solve = lq; #endif } // state functions for euler should be non-staic // deriv_imp_really list is used to track those functions if (strcmp(SYM(q2)->name, "euler") == 0) { add_deriv_imp_really(SYM(q1)->name); } delete(q2->prev); delete(q2); }else{ qtemp = q1->next; Lappendsym(solvq, SYM0); } delete(q1->prev); /* handle the error statement */ /* put one in if it isn't already there */ if (qerr == ITEM0) { #if NOCMODL sprintf(buf, "if(error){fprintf(stderr,\"%s\\n\"); nrn_complain(_p); abort_run(error);}\n", current_line()); qtemp = qerr = insertstr(qtemp, buf); #else qtemp = qerr = insertstr(qtemp, "if(error){abort_run(error);}\n"); #endif }else{ replacstr(qtemp, "if (error)"); } errstmt = newlist(); lq = lappendsym(solvq, SYM0); LST(lq) = errstmt; movelist(qtemp, qerr, errstmt); } /* go through the solvq list and construct the proper while loop and calls*/ void solvhandler() { Item *lq, *qsol, *follow; List *errstmt; Symbol *fun, *method; int numeqn, listnum, btype, steadystate; int cvodemethod_; if (!solvq) solvq = newlist(); init_disc_vars(); /*why not here?*/ ITERATE(lq, solvq) { /* remember it goes by 3's */ steadystate=0; btype = lq->itemtype; if (btype < 0) { btype = lq->itemtype = -btype; steadystate = 1; check_ss_consist(lq); } qsol = ITM(lq); lq = lq->next; method = SYM(lq); #if CVODE cvodemethod_ = 0; if (method && strcmp(method->name, "after_cvode") == 0) { method = (Symbol*)0; lq->element.sym = (Symbol*)0; cvodemethod_ = 1; } if (method && strcmp(method->name, "cvode_t") == 0) { method = (Symbol*)0; lq->element.sym = (Symbol*)0; cvodemethod_ = 2; } if (method && strcmp(method->name, "cvode_v") == 0) { method = (Symbol*)0; lq->element.sym = (Symbol*)0; cvodemethod_ = 3; } #endif lq = lq->next; errstmt = LST(lq); /* err stmt handling assumes qsol->next is where it goes. */ fun = SYM(qsol); numeqn = fun->used; listnum =fun->u.i; follow = qsol->next; /* where p[0] gets updated */ /* Check consistency of method and block type */ if (method && !(method->subtype & fun->subtype)) { Sprintf(buf, "Method %s can't be used with Block %s", method->name, fun->name); diag(buf, (char *)0); } switch (fun->subtype) { case DERF: if (method == SYM0) { method = lookup("adrunge"); } if (btype == BREAKPOINT && !steadystate) { /* derivatives recalculated after while loop */ if (strcmp(method->name, "cnexp") != 0 && strcmp(method->name, "derivimplicit") != 0 && strcmp(method->name, "euler") != 0) { fprintf(stderr, "Notice: %s is not thread safe. Complain to Hines\n", method->name); vectorize = 0; Sprintf(buf, " %s();\n", fun->name); Insertstr(follow, buf); } /* envelope calls go after the while loop */ sens_nonlin_out(follow, fun); #if CVODE cvode_interface(fun, listnum, numeqn); #endif } if (btype == BREAKPOINT) whileloop(qsol, (long)DERF, steadystate); solv_diffeq(qsol, fun, method, numeqn, listnum, steadystate, btype); break; case KINF: if (method == SYM0) { method = lookup("_advance"); } if (btype == BREAKPOINT && (method->subtype & DERF)) { #if VECTORIZE fprintf(stderr, "Notice: KINETIC with is thread safe only with METHOD sparse. Complain to Hines\n"); vectorize = 0; #endif /* derivatives recalculated after while loop */ Sprintf(buf, " %s();\n", fun->name); Insertstr(follow, buf); /* envelope calls go after the while loop */ sens_nonlin_out(follow, fun); } if (btype == BREAKPOINT) { whileloop(qsol, (long)DERF, steadystate); #if CVODE if (strcmp(method->name, "sparse") == 0) { cvode_interface(fun, listnum, numeqn); cvode_kinetic(qsol, fun, numeqn, listnum); single_channel(qsol, fun, numeqn, listnum); } #endif } solv_diffeq(qsol, fun, method, numeqn, listnum, steadystate, btype); break; case NLINF: #if VECTORIZE fprintf(stderr, "Notice: NONLINEAR is not thread safe.\n"); vectorize = 0; #endif if (method == SYM0) { method = lookup("newton"); } solv_nonlin(qsol, fun, method, numeqn, listnum); break; case LINF: #if VECTORIZE fprintf(stderr, "Notice: LINEAR is not thread safe.\n"); vectorize = 0; #endif if (method == SYM0) { method = lookup("simeq"); } solv_lineq(qsol, fun, method, numeqn, listnum); break; case DISCF: #if VECTORIZE fprintf(stderr, "Notice: DISCRETE is not thread safe.\n"); vectorize = 0; #endif if (btype == BREAKPOINT) whileloop(qsol, (long)DISCRETE, 0); Sprintf(buf, "0; %s += d%s; %s();\n", indepsym->name, indepsym->name, fun->name); replacstr(qsol, buf); break; #if 1 /* really wanted? */ case PROCED: if (btype == BREAKPOINT) { whileloop(qsol, (long)DERF, 0); #if CVODE if (cvodemethod_ == 1) { /*after_cvode*/ cvode_interface(fun, listnum, 0); } if (cvodemethod_ == 2) { /*cvode_t*/ cvode_interface(fun, listnum, 0); insertstr(qsol, "if (!cvode_active_)"); cvode_nrn_cur_solve_ = fun; } if (cvodemethod_ == 3) { /*cvode_t_v*/ cvode_interface(fun, listnum, 0); insertstr(qsol, "if (!cvode_active_)"); cvode_nrn_current_solve_ = fun; } #endif } Sprintf(buf, " %s();\n", fun->name); replacstr(qsol, buf); #if VECTORIZE Sprintf(buf, "{ %s(_threadargs_); }\n", fun->name); vectorize_substitute(qsol, buf); #endif break; #endif case PARF: #if VECTORIZE fprintf(stderr, "Notice: PARTIAL is not thread safe.\n"); vectorize = 0; #endif if (btype == BREAKPOINT) whileloop(qsol, (long)DERF, 0); solv_partial(qsol, fun); break; default: diag("Illegal or unimplemented SOLVE type: ", fun->name); break; } #if CVODE if (btype == BREAKPOINT) { cvode_valid(); } #endif /* add the error check */ Insertstr(qsol, "error ="); move(errstmt->next, errstmt->prev, qsol->next); #if VECTORIZE if (errstmt->next == errstmt->prev) { vectorize_substitute(qsol->next, ""); vectorize_substitute(qsol->prev, ""); }else{ fprintf(stderr, "Notice: SOLVE with ERROR is not thread safe.\n"); vectorize = 0; } #endif freelist(&errstmt); /* under all circumstances, on return from model, p[0] = current indepvar */ /* obviously ok if indepvar is original; if it has been changed away from time then _sav_indep will be reset to starting value of original when initmodel is called on every call to model */ #if NMODL #else if (btype == BREAKPOINT) { #if SIMSYS Sprintf(buf, "_sav_indep = %s;\n", indepsym->name); #else Sprintf(buf, "_sav_indep = _p[_indepindex];\n"); #endif Insertstr(follow, buf); } #endif } } void save_dt(q) /* save and restore the value of indepvar */ Item *q; { /*ARGSUSED*/ #if 0 /* integrators no longer increment time */ static int first=1; if (first) { first = 0; Linsertstr(procfunc, "double _savlocal;\n"); } Sprintf(buf, "_savlocal = %s;\n", indepsym->name); Insertstr(q, buf); Sprintf(buf, "%s = _savlocal;\n", indepsym->name); Insertstr(q->next, buf); #endif } char *saveindep = ""; static void whileloop(qsol, type, ss) Item *qsol; long type; int ss; { /* no solve statement except this is allowed to change the indepvar. Time passed to integrators must therefore be saved and restored. */ /* Note that when the user changes the independent variable within Scop, the while loop still uses the original independent variable. In this case 1) _break must be set to the entry value of the original independent variable 2) initmodel() must be called after each entry to model() 3) in initmodel() we are very careful not to destroy the entry value of time-- on exit it has its original value. Note that _sav_indep gets any value of time that is set within initmodel(). */ /* executing more that one for loop in a single call to model() is an error which is trapped in scop */ static int called = 0, firstderf = 1; char *cp=0; switch (type) { case DERF: case DISCRETE: if (firstderf) { /* time dependent process so create a deltastep */ double d[3]; #ifndef NeXT double atof(); #endif int i; Item *q; char sval[30]; Sprintf(buf, "delta_%s", indepsym->name); for (i=0, q=indeplist->next; i<3; i++, q=q->next) { d[i] = atof(STR(q)); } if (type == DERF) { Sprintf(sval, "%g", (d[1]-d[0])/d[2]); }else if (type == DISCRETE) { Sprintf(sval, "1.0"); } deltaindep = ifnew_parminstall(buf, sval, "", ""); firstderf = 0; #if NMODL #else Sprintf(buf, "_modl_set_dt(_dt) double _dt; { %s = _dt;}\n", deltaindep->name); Lappendstr(procfunc, buf); #endif } if (type == DERF) { cp = "dt"; }else if (type == DISCRETE) { cp = "0.0"; } if (ss) { return; } break; default: /*SUPPRESS 622*/ assert(0); } #if NMODL if (strcmp(indepsym->name, "t") != 0) { diag("The independent variable name must be `t'", (char *)0); } #else Sprintf(buf, "_save = _break = %s; %s = _sav_indep;\n", indepsym->name, indepsym->name); Insertstr(qsol, buf); #if !SIMSYS Sprintf(buf, "if (_p + _indepindex != &%s) {initmodel(_pp); %s = _sav_indep;}\n", indepsym->name, indepsym->name); Insertstr(qsol, buf); #endif #endif if (called) { Fprintf(stderr, "Warning: More than one integrating SOLVE statement in an \ BREAKPOINT block.\nThe simulation will be incorrect if more than one is used \ at a time.\n"); } #if NMODL #else Sprintf(buf, "if (%s < _break) {\n",indepsym->name); Insertstr(qsol, buf); /* ensure that there are an integer number of steps / break */ if (type == DERF) { Sprintf(buf, " { int _nstep; double _dt, _y;\n\ _y = _break - %s; _dt = %s;\n", indepsym->name, "dt"); Insertstr(qsol, buf); Insertstr(qsol, "_nstep = (int)(_y/_dt + .9);\n if (_nstep==0) _nstep = 1;\n"); Sprintf(buf, "%s = _y/((double)_nstep);\n", "dt"); Insertstr(qsol, buf); Sprintf(buf, "\n }\n"); Insertstr(qsol, buf); } if (type == DERF) { Sprintf(buf, "_break -= .5* %s;\n", "dt"); Insertstr(qsol, buf); } #endif #if NMODL /* no longer a for loop */ #else Sprintf(buf, "for (; %s < _break; %s += %s) {\n", indepsym->name, indepsym->name, cp); Insertstr(qsol, buf); /* close the while loop; note that integrators have been called */ if (type == DERF) { Sprintf(buf, "\n}}\n %s = _save;\n", indepsym->name); }else if (type == DISCRETE) { Sprintf(buf, "\n}}\n"); } Insertstr(qsol->next,buf); #endif if (!called) { /* fix up initmodel as per 3) above. In cout.c _save is declared */ #if NMODL Sprintf(buf, " _save = %s;\n %s = 0.0;\n", indepsym->name, indepsym->name); saveindep = stralloc(buf, (char *)0); #else Sprintf(buf, "%s0", indepsym->name); IGNORE(ifnew_parminstall(buf, STR(indeplist->prev->prev), STR(indeplist->prev), "")); Sprintf(buf, " _save = %s;\n %s = %s0;\n", indepsym->name, indepsym->name, indepsym->name); saveindep = stralloc(buf, (char *)0); #endif /* Assert no more additions to initfunc involving the value of time */ Sprintf(buf, " _sav_indep = %s; %s = _save;\n", indepsym->name, indepsym->name); Lappendstr(initfunc, buf); #if VECTORIZE vectorize_substitute(initfunc->prev, ""); #endif } called++; } /* steady state consistency means that KINETIC blocks whenever solved must invoke same integrator (default is advance) and DERIVATIVE blocks whenever solved must invoke the derivimplicit method. */ static void check_ss_consist(qchk) Item *qchk; { Item *q; Symbol *fun, *method; ITERATE(q, solvq) { fun = SYM(ITM(q)); if (fun == SYM(qchk)) { method= SYM(q->next); switch (q->itemtype) { case DERF: if (!method || strcmp("derivimplicit", method->name)!=0) { diag("STEADYSTATE requires all SOLVE's of this DERIVATIVE block to use the\n\ `derivimplicit' method:", fun->name); } break; case KINF: if (SYM(qchk->next) != method || (method && strcmp("sparse", method->name) != 0)){ diag("STEADYSTATE requires all SOLVE's of this KINETIC block to use the\n\ same method (`advance' or `sparse'). :", fun->name); } break; default: diag("STEADYSTATE only valid for SOLVEing a KINETIC or DERIVATIVE block:", fun->name); break; } } q = q->next->next; } } mod2c-8.2.2/src/mod2c_core/symbol.c000066400000000000000000000072211425457616700170260ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" #include "modl.h" #include "parse1.h" #include "symbol.h" List *symlist[128]; /* symbol table: linked list first char gives which list to use,but*/ List *symlistlist; /* for a stack of local symbol lists */ void symbol_init() { int i; symlistlist = newlist(); for (i=0; i<128; i++) { /* more than we need */ symlist[i] = newlist(); } } Symbol *lookup(s) /* find s in symbol table */ char *s; { Item *sp; ITERATE(sp, symlist[s[0]]) { if (strcmp(SYM(sp)->name, s) == 0) { return SYM(sp); } } return SYM0; /* 0 ==> not found */ } Symbol *checklocal(sym) Symbol *sym; { Item *sp; List *sl; char *s; s = sym->name; /* look in local lists */ ITERATE(sl, symlistlist) ITERATE(sp, LST(sl)) { if (strcmp(SYM(sp)->name+2, s) == 0) { /*get past _l*/ return SYM(sp); } } return sym; } Symbol *install(s, t) /* install s in the list symbol table with type t*/ char *s; int t; { Symbol *sp; List *sl; if (t == STRING) { sl = symlist[0]; }else if (t == -1) { /*install on top local list see below*/ t = NAME; assert(symlistlist->next != symlistlist); sl = LST(symlistlist->next); }else{ sl = symlist[s[0]]; } sp = (Symbol *) emalloc(sizeof(Symbol)); sp->name = stralloc(s, (char *)0); sp->type = t; sp->subtype = 0; #if NMODL sp->nrntype = 0; sp->assigned_to_ = 0; sp->no_threadargs = 0; #if CVODE sp->slist_info_ = (int*)0; #endif #endif sp->u.str = (char *)0; sp->used = 0; sp->usage = 0; sp->araydim = 0; sp->discdim = 0; sp->level = 100; /* larger than any reasonable submodel level */ Linsertsym(sl, sp); /*insert at head of list*/ return sp; } void pushlocal() { Item * q; q = linsertsym(symlistlist, SYM0); /*the type is irrelevant*/ LST(q) = newlist(); } void poplocal() /* a lot of storage leakage here for symbols we are guaranteed not to need */ { List *sl; Item *i, *j; assert(symlistlist->next != symlistlist); sl = LST(symlistlist->next); for (i = sl->next; i != sl; i = j) { j = i->next; delete(i); } delete(symlistlist->next); } Symbol *copylocal(s) Symbol *s; { if (s->name[0] == '_') { Sprintf(buf, "%s", s->name); }else{ Sprintf(buf, "_l%s", s->name); } return install(buf, -1); } mod2c-8.2.2/src/mod2c_core/symbol.h000077500000000000000000000023241425457616700170350ustar00rootroot00000000000000/* /local/src/master/nrn/src/nmodl/symbol.h,v 4.1 1997/08/30 20:45:37 hines Exp */ /* symbol.h,v * Revision 4.1 1997/08/30 20:45:37 hines * cvs problem with branches. Latest nmodl stuff should now be a top level * * Revision 4.0.1.1 1997/08/08 17:24:05 hines * nocmodl version 4.0.1 * * Revision 4.0 1997/08/08 17:06:32 hines * proper nocmodl version number * * Revision 1.1.1.1 1994/10/12 17:21:33 hines * NEURON 3.0 distribution * * Revision 8.0 89/09/22 17:27:04 nfh * Freezing * * Revision 7.0 89/08/30 13:32:42 nfh * Rev 7 is now Experimental; Rev 6 is Testing * * Revision 6.0 89/08/14 16:27:21 nfh * Rev 6.0 is latest of 4.x; now the Experimental version * * Revision 4.0 89/07/24 17:03:52 nfh * Freezing rev 3. Rev 4 is now Experimental * * Revision 3.1 89/07/07 16:55:21 mlh * FIRST LAST START in independent SWEEP higher order derivatives * * Revision 1.1 89/07/06 14:52:48 mlh * Initial revision * */ extern List *symlist[]; #define SYMITER(arg1) for (i = 'A'; i <= 'z'; i++)\ ITERATE(qs, symlist[i])\ if ((s = SYM(qs))->type == arg1) #define SYMITER_STAT for (i='A'; i <= 'z'; i++)\ ITERATE(qs, symlist[i])\ if ((s = SYM(qs))->subtype & STAT) mod2c-8.2.2/src/mod2c_core/units.c000066400000000000000000000422751425457616700166730ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* /local/src/master/nrn/src/modlunit/units.c,v 1.5 1997/11/24 16:19:13 hines Exp */ /* Mostly from Berkeley */ #include #include #include #include #include "units.h" #include #ifndef USE_LEGACY_UNITS #define USE_LEGACY_UNITS 0 #endif int unitonflag = 1; static int UnitsOn = 0; extern double fabs(); extern void diag(); #define IFUNITS {if (!UnitsOn) return;} #define OUTTOLERANCE(arg1,arg2) (fabs(arg2/arg1 - 1.) > 1.e-5) #define NTAB 601 /* if MODLUNIT environment variable not set then look in the following places*/ #if MAC static char *dfile = ":lib:nrnunits.lib"; #else #if defined(NEURON_DATA_DIR) static char *dfile = NEURON_DATA_DIR"/lib/nrnunits.lib"; #else static char *dfile = "/usr/lib/units"; #endif #endif #if defined(__TURBOC__) || defined(__GO32__) static char *dfilealt = "/nrn/lib/nrnunits.lib"; #else #if MAC static char *dfilealt = "::lib:nrnunits.lib"; #else static char *dfilealt = "../../share/lib/nrnunits.lib"; #endif #endif static char *unames[NDIM]; static double getflt(); static void fperr(); static int lookup(); static struct table *hash(); static void chkfperror(); static void units(); static int pu(); static int convr(); static void init(); static int get(); extern void Unit_push(char*); static struct table { double factor; #if -1 == '\377' char dim[NDIM]; #else signed char dim[NDIM]; #endif char *name; } table[NTAB]; static char names[NTAB*10]; static struct prefix { double factor; char *pname; } prefix[] = { 1e-18, "atto", 1e-15, "femto", 1e-12, "pico", 1e-9, "nano", 1e-6, "micro", 1e-3, "milli", 1e-2, "centi", 1e-1, "deci", 1e1, "deka", 1e2, "hecta", 1e2, "hecto", 1e3, "kilo", 1e6, "mega", 1e6, "meg", 1e9, "giga", 1e12, "tera", 0.0, 0 }; static FILE *inpfile; static int fperrc; static int peekc; static int dumpflg; static char *pc; static int Getc(inp) FILE *inp; { if (inp != stdin) { #if MAC int c = getc(inp); if (c == '\r') { c = '\n';} return c; #else return getc(inp); #endif }else if (pc && *pc) { return (int)(*pc++); }else{ return (int)('\n'); } } #define UNIT_STK_SIZE 20 static struct unit unit_stack[UNIT_STK_SIZE], *usp; void unit_pop() { IFUNITS assert(usp >= unit_stack); --usp; } void unit_swap() { /*exchange top two elements of stack*/ struct unit *up; int i, j; double d; IFUNITS assert(usp > unit_stack); up = usp -1; d = usp->factor; usp->factor = up->factor; up->factor = d; for (i=0; idim[i]; usp->dim[i] = up->dim[i]; up->dim[i] = j; } } double unit_mag() { /* return unit magnitude that is on stack */ return usp->factor; } void unit_mag_mul(d) double d; { usp->factor *= d; } void punit() { struct unit * i; for (i=usp; i!=unit_stack-1; --i) { printf("%s\n", Unit_str(i)); } } void ucopypop(up) struct unit *up; { int i; for (i=0; idim[i] = usp->dim[i]; } up->factor = usp->factor; up->isnum = usp->isnum; unit_pop(); } void ucopypush(up) struct unit *up; { int i; Unit_push(""); for (i=0; idim[i] = up->dim[i]; } usp->factor = up->factor; usp->isnum = up->isnum; } void Unit_push(string) char *string; { IFUNITS assert(usp < unit_stack + (UNIT_STK_SIZE - 1)); ++usp; pc = string; if (string) { usp->isnum = 0; }else{ pc = ""; usp->isnum = 1; } convr(usp); /*printf("unit_push %s\n", string); units(usp);*/ } void unit_push_num(d) double d; { Unit_push(""); usp->factor = d; } void unitcheck(s) char *s; { Unit_push(s); unit_pop(); } char * unit_str() { /* return top of stack as units string */ if (!UnitsOn) return ""; return Unit_str(usp); } void install_units(s1, s2) /* define s1 as s2 */ char *s1, *s2; { struct table *tp; int i; IFUNITS Unit_push(s2); tp = hash(s1); if (tp->name) { printf("Redefinition of units (%s) to:", s1); units(usp); printf(" is ignored.\nThey remain:"); Unit_push(s1); units(usp); diag("Units redefinition", (char *)0); } tp->name = s1; tp->factor = usp->factor; for (i=0; idim[i] = usp->dim[i]; } unit_pop(); } void check_num() { struct unit * up = usp -1; /*EMPTY*/ if (up->isnum && usp->isnum) { ; } else { up->isnum = 0; } } void unit_mul() { /* multiply next element by top of stack and leave on stack */ struct unit *up; int i; IFUNITS assert(usp > unit_stack); check_num(); up = usp -1; for (i=0; idim[i] += usp->dim[i]; } up->factor *= usp->factor; unit_pop(); } void unit_div() { /* divide next element by top of stack and leave on stack */ struct unit *up; int i; IFUNITS assert(usp > unit_stack); check_num(); up = usp -1; for (i=0; idim[i] -= usp->dim[i]; } up->factor /= usp->factor; unit_pop(); } void Unit_exponent(val) int val; { /* multiply top of stack by val and leave on stack */ int i; double d; IFUNITS assert(usp >= unit_stack); for (i=0; idim[i] *= val; } d = usp->factor; for (i=1; ifactor *= d; } } int unit_cmp_exact() { /* returns 1 if top two units on stack are same */ struct unit *up; int i; {if (!UnitsOn) return 0;} up = usp - 1; if (unitonflag) { if (up->dim[0] == 9 || usp->dim[0] == 9) { return 1; } for (i=0; idim[i] != usp->dim[i]) { chkfperror(); return 0; } } if (OUTTOLERANCE(up->factor, usp->factor)) { chkfperror(); return 0; } } return 1; } /* ARGSUSED */ static void print_unit_expr(i) int i; {} void Unit_cmp() { /*compares top two units on stack. If not conformable then gives error. If not same factor then gives error. */ struct unit *up; int i; IFUNITS assert(usp > unit_stack); up = usp - 1; if (usp->isnum) { unit_pop(); return; } if (up->isnum) { for (i=0; i < NDIM; i++) { up->dim[i] = usp->dim[i]; } up->factor = usp->factor; up->isnum = 0; } if (unitonflag && up->dim[0] != 9 && usp->dim[0] != 9) { for (i=0; idim[i] != usp->dim[i]) { chkfperror(); print_unit_expr(2); fprintf(stderr, "\nunits:"); units(usp); print_unit_expr(1); fprintf(stderr, "\nunits:"); units(up); diag("The units of the previous two expressions are not conformable","\n"); } } if (OUTTOLERANCE(up->factor, usp->factor)) { chkfperror(); fprintf(stderr, "The previous primary expression with units: %s\n\ is missing a conversion factor and should read:\n (%g)*(", Unit_str(usp), usp->factor/up->factor); print_unit_expr(2); diag(")\n", (char *)0); } } unit_pop(); return; } int unit_diff() { /*compares top two units on stack. If not conformable then return 1, if not same factor return 2 if same return 0 */ struct unit *up; int i; if (!UnitsOn) return 0; assert(usp > unit_stack); up = usp - 1; if (up->dim[0] == 9 || usp->dim[0] == 9) { unit_pop(); return 0; } if (usp->isnum) { unit_pop(); return 0; } if (up->isnum) { for (i=0; i < NDIM; i++) { up->dim[i] = usp->dim[i]; } up->factor = usp->factor; up->isnum = 0; } for (i=0; idim[i] != usp->dim[i]) { return 1; } } if (OUTTOLERANCE(up->factor, usp->factor)) { return 2; } unit_pop(); return 0; } static void chkfperror() { if (fperrc) { diag("underflow or overflow in units calculation", (char *)0); } } void dimensionless() { /* ensures top element is dimensionless */ int i; IFUNITS assert(usp >= unit_stack); if (usp->dim[0] == 9) {return;} for (i=0; idim[i] != 0) { units(usp); diag("The previous expression is not dimensionless", (char *)0); } } } void unit_less() { /* ensures top element is dimensionless with factor 1*/ IFUNITS if (unitonflag) { dimensionless(); if (usp->dim[0]!=9 && OUTTOLERANCE(usp->factor,1.0)) { fprintf(stderr, "The previous expression needs the conversion factor (%g)\n", 1./(usp->factor)); diag("", (char *)0); } } unit_pop(); } void unit_stk_clean() { IFUNITS usp = unit_stack - 1; } #if MODL||NMODL||HMODL||SIMSYS extern void unit_init(); void modl_units() { static int first=1; unitonflag = 1; if (first) { unit_init(); first = 0; } } #endif void unit_init() { char* s; char buf[256]; inpfile = (FILE*)0; UnitsOn = 1; s = getenv("MODLUNIT"); if (s) { if ((inpfile = fopen(s, "r")) == (FILE *)0) { diag("Bad MODLUNIT environment variable. Cant open:", s); } } if (!inpfile) { fprintf(stderr, "Set a MODLUNIT environment variable path to the units table file\n"); fprintf(stderr, "Cant open units table in either of:\n%s\n", buf); diag(dfile, dfilealt); } signal(8, fperr); init(); unit_stk_clean(); } #if 0 void main(argc, argv) char *argv[]; { register i; register char *file; struct unit u1, u2; double f; if(argc>1 && *argv[1]=='-') { argc--; argv++; dumpflg++; } file = dfile; if(argc > 1) file = argv[1]; if ((inpfile = fopen(file, "r")) == NULL) { printf("no table\n"); exit(1); } signal(8, fperr); init(); loop: fperrc = 0; printf("you have: "); if(convr(&u1)) goto loop; if(fperrc) goto fp; loop1: printf("you want: "); if(convr(&u2)) goto loop1; for(i=0; ifactor); {int seee=0; for (ucp=buf; *ucp; ucp++) { if (*ucp == 'e') seee=1; if (seee) *ucp = ucp[1]; } if (seee) ucp--;} f = 0; for(i=0; idim[i], i, f); if(f&1) { *ucp++ = '/'; f = 0; for(i=0; idim[i], i, f); } *ucp = '\0'; return buf; } static int pu(int u, int i, int f) { if(u > 0) { if(f&2) *ucp++ = '-'; if(unames[i]) { sprintf(ucp,"%s", unames[i]); ucp += strlen(ucp); } else{ sprintf(ucp,"*%c*", i+'a'); ucp += strlen(ucp); } if(u > 1) *ucp++ = (u+'0'); return(2); } if(u < 0) return(1); return(0); } static int convr(up) struct unit *up; { register struct unit *p; register int c; register char *cp; char name[20]; int den, err; p = up; for(c=0; cdim[c] = 0; p->factor = getflt(); if(p->factor == 0.) { p->factor = 1.0; } err = 0; den = 0; cp = name; loop: switch(c=get()) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': case '/': case ' ': case '\t': case '\n': if(cp != name) { *cp++ = 0; cp = name; err |= lookup(cp, p, den, c); } if(c == '/') den++; if(c == '\n') return(err); goto loop; } *cp++ = c; goto loop; } static int lookup(char* name, struct unit* up, int den, int c) { register struct unit *p; register struct table *q; register int i; char *cp1, *cp2; double e; p = up; e = 1.0; loop: q = hash(name); if(q->name) { l1: if(den) { p->factor /= q->factor*e; for(i=0; idim[i] -= q->dim[i]; } else { p->factor *= q->factor*e; for(i=0; idim[i] += q->dim[i]; } if(c >= '2' && c <= '9') { c--; goto l1; } return(0); } for(i=0; (cp1 = prefix[i].pname) != 0; i++) { cp2 = name; while(*cp1 == *cp2++) if(*cp1++ == 0) { cp1--; break; } if(*cp1 == 0) { e *= prefix[i].factor; name = cp2-1; goto loop; } } /*EMPTY*/ for(cp1 = name; *cp1; cp1++); if(cp1 > name+1 && *--cp1 == 's') { *cp1 = 0; goto loop; } fprintf(stderr, "Need declaration in UNITS block of the form:\n\ (%s) (units)\n", name); diag("Cannot recognize the units: ", name); /* printf("cannot recognize %s\n", name);*/ return(1); } static int equal(s1, s2) char *s1, *s2; { register char *c1, *c2; c1 = s1; c2 = s2; while(*c1++ == *c2) if(*c2++ == 0) return(1); return(0); } static void init() { register char *cp; register struct table *tp, *lp; int c, i, f, t; char *np; cp = names; for(i=0; iname = np; lp->factor = 1.0; lp->dim[i] = 1; } lp = hash(""); lp->name = cp-1; lp->factor = 1.0; l0: c = get(); if(c == 0) { #if 0 printf("%d units; %d bytes\n\n", i, cp-names); #endif if(dumpflg) for(tp = table; tp < table+NTAB; tp++) { if(tp->name == 0) continue; printf("%s", tp->name); units((struct unit *)tp); } fclose(inpfile); inpfile = stdin; return; } if(c == '/') { while(c != '\n' && c != 0) c = get(); goto l0; } if(c == '\n') goto l0; np = cp; while(c != ' ' && c != '\t') { *cp++ = c; c = get(); if (c==0) goto l0; if(c == '\n') { *cp++ = 0; tp = hash(np); if(tp->name) goto redef; tp->name = np; tp->factor = lp->factor; for(c=0; cdim[c] = lp->dim[c]; i++; goto l0; } } *cp++ = 0; lp = hash(np); if(lp->name) goto redef; convr((struct unit *)lp); lp->name = np; f = 0; i++; if(lp->factor != 1.0) goto l0; for(c=0; cdim[c]; if(t>1 || (f>0 && t!=0)) goto l0; if(f==0 && t==1) { if(unames[c]) goto l0; f = c+1; } } if(f>0) unames[f-1] = np; goto l0; redef: printf("redefinition %s\n", np); goto l0; } #if USE_LEGACY_UNITS == 0 /* Convert str to double using atof. Allows consistency with BlueBrain/nmodl */ static double getflt() { int c; char str[100]; char* cp; double d_modern; cp = str; do c = get(); while(c == ' ' || c == '\t'); l1: if(c >= '0' && c <= '9') { *cp++ = c; c = get(); goto l1; } if(c == '.') { *cp++ = c; c = get(); goto l1; } if(c == '+' || c == '-') { *cp++ = 'e'; *cp++ = c; c = get(); while(c >= '0' && c <= '9') { *cp++ = c; c = get(); } } *cp = '\0'; d_modern = atof(str); if(c == '|') { d_modern /= getflt(); return d_modern; } peekc = c; return(d_modern); } #else /* USE_LEGACY_UNITS == 1 */ static double getflt() { register int c, i, dp; double d, e; int f; d = 0.; dp = 0; do c = get(); while(c == ' ' || c == '\t'); l1: if(c >= '0' && c <= '9') { d = d*10. + c-'0'; if(dp) dp++; c = get(); goto l1; } if(c == '.') { dp++; c = get(); goto l1; } if(dp) dp--; if(c == '+' || c == '-') { f = 0; if(c == '-') f++; i = 0; c = get(); while(c >= '0' && c <= '9') { i = i*10 + c-'0'; c = get(); } if(f) i = -i; dp -= i; } e = 1.; i = dp; if(i < 0) i = -i; while(i--) e *= 10.; if(dp < 0) d *= e; else d /= e; if(c == '|') return(d/getflt()); peekc = c; return(d); } #endif /* USE_LEGACY_UNITS == 1 */ static int get() { register int c; /*SUPPRESS 560*/ if((c=peekc) != 0) { peekc = 0; return(c); } c = Getc(inpfile); if (c == '\r') { c = Getc(inpfile); } if (c == EOF) { if (inpfile == stdin) { printf("\n"); exit(0); } return(0); } return(c); } static struct table * hash(name) char *name; { register struct table *tp; register char *np; register unsigned h; h = 0; np = name; while(*np) h = h*57 + *np++ - '0'; if( ((int)h)<0) h= -(int)h; h %= NTAB; tp = &table[h]; l0: if(tp->name == 0) return(tp); if(equal(name, tp->name)) return(tp); tp++; if(tp >= table+NTAB) tp = table; goto l0; } static void fperr(sig) int sig; { signal(8, fperr); fperrc++; } void nrnunit_dynamic_str(char* buf, const char* name, char* u1, char* u2) { double u; Unit_push(u1); Unit_push(u2); unit_div(); u = unit_mag(); unit_pop(); #if USE_LEGACY_UNITS sprintf(buf, "\ndouble %s = %g;\n", name, u); #else /* compiler can't read %a format til c++17 (or c99) */ sprintf(buf, "\ndouble %s = /* %a; */ %.18g;\n", name, u, u); #endif } mod2c-8.2.2/src/mod2c_core/units.h000077500000000000000000000003231425457616700166670ustar00rootroot00000000000000#define NDIM 10 struct unit { double factor; #if -1 == '\377' char dim[NDIM]; #else signed char dim[NDIM]; #endif int isnum; }; extern char *Unit_str(); extern int unit_diff(); extern int unit_cmp_exact(); mod2c-8.2.2/src/mod2c_core/version.c000066400000000000000000001173461425457616700172200ustar00rootroot00000000000000/* Copyright (c) 2016, Blue Brain Project 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. Neither the name of the copyright holder nor the names of its contributors may 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 HOLDER 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. */ #include "nmodlconf.h" /* $Header$ */ /* $Log$ Revision 1.2 2005/10/04 20:55:32 hines The bg1 branch is merged into the Main trunk. That branch contains all the BlueGene specific enhancements and many general Parallel Network simulation enhancements that were useful for efficient simulation on the BlueGene. The bottom line is that a 25000 cell Cortical network eleptogenesis model by Paul Bush, re-written for parallel simulation by Bill Lytton shows linear speedup on up to 2500 cpus on the BlueGene. This model generated approximately 200000 spikes and managed over 100,000,000 NetCons. Revision 1.1.1.1.72.1 2005/09/25 16:59:51 hines A first pass at configure support for cross compiling. Not perfect but much superior to what existed prior to this commit. The problem is that although most of the binaries constructed are executed on the host machine, there are three, hoc_e, modlunit, and nocmodl, that are executed on the build machine. This means potentially different configuration, compilers, and makefile dependency mechanisms. The current solution requires two passes. The first pass is to configure with the --with-nmodl-only option and then make and make install. That pass constructs a nmodlconf.h file which is the dual to nrnconf.h. The second pass should configure with the --without-nmodl option and then make and make install. Note that it is important to properly set CC, CXX, CFLAGS, CXXFLAGS, LIBS and any other thing that is distinct between the configurations. Also note that the BlueGene is special since those variables are set to proper default values for both passes. In this case the nmodl pass should have the configuration options --enable-bluegene --with-nmodl-only and the second pass does NOT need the --without-nmodl option and the single option --enable-bluegene suffices. One can switch to the build configuration without affecting the host and vice versa since .h.in files are not shared. That is helpful as there are no files that have to be recompiled due to the switch. Revision 1.1.1.1 2003/02/11 18:36:08 hines NEURON Simulation environment. Unreleased 5.4 development version. Revision 1.1.1.1 2003/01/01 17:46:33 hines NEURON -- Version 5.4 2002/12/23 from prospero as of 1-1-2003 Revision 1.1.1.1 2002/06/26 16:23:07 hines NEURON 5.3 2002/06/04 * Revision 1.1.1.1 2001/01/01 20:30:34 hines * preparation for general sparse matrix * * Revision 1.2 2000/03/27 14:17:44 hines * All sources now include nrnconf.h instead of config.h so that minor * option changes (eg in src/parallel/bbsconf.h) do not require recompilation * of everything. * * Revision 1.1.1.1 2000/03/09 13:55:34 hines * almost working * * Revision 4.3 1997/11/13 19:53:08 hines * LONGITUDINAL_DIFFUSION area {state} allowed in KINETIC block * same syntax as COMPARTMENT statement. * Units checking not established yet but area should be in um2 and * the COMPARTMENT volume units should be um3/um. * If the longitudinal area is affected by diam then diam should * appear explicitly in the area expression (generally as diam*diam/4 * but perhaps some coordinate systems may have area that scales * linearly with diam). * Longitudinal diffusion works correctly with changing diameter and * rallbranch. It works with cvode but the linear solver for it * is currently equivalent to modified euler. With CVODE and * cvode.jacobian(1) to use a full matrix the approach to steady state * is fast if there are not too many states. It would be nice to * do some approimate tridiagonal system approaches for the built-in * linear solver. * * Revision 4.2 1997/10/20 14:59:33 hines * nocmodl file.mod allowed (ie suffix is allowed) * * Revision 4.1 1997/08/30 20:45:38 hines * cvs problem with branches. Latest nmodl stuff should now be a top level * * Revision 4.0.1.1 1997/08/08 17:24:06 hines * nocmodl version 4.0.1 * * Revision 4.0 1997/08/08 17:22:24 hines * version 4.0 of nocmodl * * Revision 1.4 1997/08/08 17:21:52 hines * version 4.0 of nocmodl * * Revision 1.3 1997/08/08 17:06:34 hines * proper nocmodl version number * * Revision 1.2 1997/08/08 17:03:28 hines * correct nocmodl language version * * Revision 1.1.1.1 1994/10/12 17:21:37 hines * NEURON 3.0 distribution * * Revision 9.194 1994/10/03 17:49:49 hines * more flexibility as to relation of erev and concentrations and their types * * Revision 9.193 1994/09/26 18:37:06 hines * forgot to checkin last time * * Revision 9.192 1994/09/26 18:20:19 hines * USEION ... VALENCE real * required when a model uses an ion other than na, k, ca * USEION ... WRITE cai, cao * promotes cai, cao to STATE * USEION ... READ cai, cao * promotes cai, cao to CONST * * Revision 9.191 1994/09/20 14:45:44 hines * port to dec alpha * * Revision 9.190 1994/09/20 14:44:11 hines * port to dec alpha * * Revision 9.189 1994/08/23 15:45:09 hines * In SOLVE procedure the VERBATIM return 0; is no longer * requires since all procedures have this by default. * In nocmodl, INDEPENDENT no longer required since if doesn't exist then * t (ms) automatically declared. * * Revision 9.188 1994/08/18 12:12:43 hines * properly put pragmas in with if... else stmts. * Dont use pragmas in nonvectorized part of kinetic block * * Revision 9.187 1994/08/05 14:11:14 hines * NullParameter replaces null args in Imakefile * * Revision 9.186 1994/08/04 20:03:55 hines * forgot to remove 1 && from kinetic vectorize testbed * * Revision 9.185 1994/07/30 17:14:21 hines * standard check for bison and changes to kinetic vectorization surrounded * by proper conditional preprocessor directives * * Revision 9.184 1994/07/26 14:04:22 hines * avoid objectcenter warning about retrieving int from pointer when * procedure is solved. The pointer in question is null and the int * is never used. * * Revision 9.183 1994/07/25 20:59:38 hines * wrong number of args in an emission of MATELM in new style. * * Revision 9.182 1994/07/21 13:11:16 hines * allow vectorization of kinetic blocks on cray when using sparse method. * not tested yet * * Revision 9.181 1994/05/23 17:56:52 hines * error in handling MODL_INCLUDE when no file exists * * Revision 9.180 1994/05/18 18:11:56 hines * INCLUDE "file" * tries originalpath/file ./file MODL_INCLUDEpaths/file * * Revision 9.179 1994/05/09 19:10:30 hines * pointprocess.has_loc() returns true if point process located in section * * Revision 9.178 1994/05/02 12:48:35 hines * on abort with NOCMODL call nrn_complain(_p) to tell location where * failure occurred (only SOLVE statement) and print line and .mod file * * Revision 9.177 1994/03/16 20:51:30 hines * use getcwd instead of getwd. More portable * * Revision 9.176 1994/03/08 17:51:05 hines * allow help syntax, ? treated same as : * send the filename and mechname to hoc during registration * * Revision 9.175 1994/02/24 19:25:58 hines * better error message if no declaration and gets caught in decode_ustr * * Revision 9.174 1993/11/04 15:53:20 hines * port to solaris2 (no more warnings) * * Revision 9.173 1993/07/09 17:21:34 hines * fix error in vectorization of solve from last change * * Revision 9.172 93/07/09 16:28:36 hines * point processes now work correctly when they are electrodes and an * extracellular mechananism is present. * vclmp.mod and stim.mod are electrodes * positive electrode current causes depolarization (normal mechanism * current is positive outward) * When ELECTRODE_CURRENT keyword is present then v refers to * vmembrane+vext * Note : no warning is given if there are membrane currents within * the same model. they are also silently treated the same way as * an electrode * * Revision 9.171 93/07/08 14:46:09 hines * Alternative to NONSPECIFIC_CURRENT is ELECTRODE_CURRENT * at this time is identical to old way. Introduced because membrane * mechanisms for electrode currents don't work right because the * current is assumed to pass from the extracellular space to the inside * and thus current injection does not change vext (and it is opposite in * sign to what one would expect). This change is not complete here. Only * the scaffolding is now in place and it has been verified to be identical * to the old way. The change is mostly to non-vectorized models and * now * void nrn_cur(Node*, double*, Datum*) so that the model gets v directly * from the node and changes d and rhs from the node. * * Revision 9.170 93/05/17 11:06:54 hines * PI defined by some so undefing it * * Revision 9.169 93/04/28 10:01:12 hines * local right hand side for sparse. used to be extern modl_rhs now it is * coef... This allows multiple models to use sparse. * * Revision 9.168 93/04/23 11:13:45 hines * model keeps sparse method state in its own static area so sparse * can solve different sets of equations * * Revision 9.167 93/04/21 11:06:10 hines * lineq blocks do not return error number * nocpout point processes dparam element 2 reserved for a pointer to * Point_process * * Revision 9.166 93/03/21 17:47:57 hines * for some reason vectorized models with functions with no args * were begin translated at f(ix_,) * * Revision 9.165 93/02/25 13:25:51 hines * need_memb called with symbol instead of name * * Revision 9.164 93/02/23 14:51:59 hines * compiles with dos * * Revision 9.163 93/02/23 14:48:15 hines * compiles with DOS * * Revision 9.162 93/02/23 14:43:33 hines * works under DOS * * Revision 9.161 93/02/15 08:57:33 hines * linux * * Revision 9.159 93/02/11 16:55:48 hines * minor mods for NeXT * * Revision 9.158 93/02/02 10:32:50 hines * create static func before usage * * Revision 9.157 93/02/01 15:18:19 hines * static functions should be declared before use. * inline is keyword for some compilers. * * Revision 9.156 93/01/23 13:13:57 hines * The NeXT does not like to include files twice so nmodl_redef.h * has been separated into nmodl1_redef.h and nmodl2_redef.h * * Revision 9.155 93/01/05 11:05:46 hines * functions with no suffix still need to be declared * * Revision 9.154 92/11/10 11:56:22 hines * when compiling a translated model on the CRAY (with _CRAY defined as 1) * the check table functions are taken out of the loops. This is * not entirely safe if tables are used (and dependencies have changed) * in direct calls to functions that call functions with tables. It is * reasonably safe for finitialize(), fadvance(), fcurrent(), and * calling the hoc_function itself. * * Revision 9.153 92/10/30 16:06:36 hines * echo proper number of shift/reduce conflicts * * Revision 9.152 92/10/27 09:28:20 hines * all point processes use same steer_point_process in nrnoc/point.c * so there is no need to register a special one. * * Revision 9.151 92/10/24 16:31:43 hines * sets prop->param_size for use in notifying interviews when arrays are freed * * Revision 9.150 92/10/11 15:40:49 hines * forgot to declare _n_func for tables * * Revision 9.149 92/10/09 08:15:13 hines * for nrnoc, change in point process output style. now creates a built * in object for point processes. lives in SUN4nocmod * * Revision 9.148 92/10/05 13:05:03 hines * table functions separated into name(), _check_name(), _f_name(), * and _n_name(). * name() is robust in that it will steer to analytic or table and will * check that the table is uptodate. note _n_name is a table that does * no checking. * * Revision 9.147 92/09/27 17:46:21 hines * vectorized channel densities with _method3 fill thisnode.GC,EC instead * of rhs,d * * Revision 9.146 92/09/25 13:55:18 hines * the includes at beginning of lines must be hidden from the preprocessor * or else some machines will try to include them. * * Revision 9.145 92/08/06 10:13:37 hines * the check table function did not have _ix defined * * Revision 9.144 92/08/06 09:59:17 hines * put cray pragmas at appropriate places * get rid of initmodel references to saveing t and incrementing ninit * * Revision 9.143 92/08/06 09:04:22 hines * table checking and creation moved into separate procedure. still called * everytime function is called. * * Revision 9.142 92/08/05 16:23:18 hines * can vectorize hh. need work on tables though. * * Revision 9.140 92/07/27 11:34:15 hines * some bugs fixed. no vectorizing except for SOLVE procedure (and that not done yet) * * Revision 9.139 92/07/27 10:11:25 hines * Can do some limited vectorization. Much remains. Often fails * * Revision 9.138 92/06/01 12:04:16 hines * NEURON { EXTERNAL name, name, ...} * translates to extern double name; * GLOBAL changed to translate to * #define name name_suffix * extern double name * * Revision 9.137 92/05/05 08:39:51 hines * last addition botched because line put in wrong place * * Revision 9.136 92/05/05 08:33:27 hines * need to link with math library (at least on RS6000) * * Revision 9.135 92/04/15 16:21:35 hines * recursive define problem with GLOBFUNCT when suffix was nothing, fixed * * Revision 9.134 92/03/31 06:51:21 hines * CONSTANT could not be a negative number. Fixed * * Revision 9.133 92/03/19 15:15:18 hines * creates a nrn_initialize function that will be called from finitialize(). * * Revision 9.132 92/02/18 13:25:51 hines * modl_rhs must be extern or else turboc won't connect it with sparse.c * * Revision 9.131 92/02/17 12:53:55 hines * GLOBFUNCT for parsact so table functions declare external instead of * static. * * Revision 9.130 92/02/17 10:25:13 hines * global modl functions declared with suffixes using #define * * Revision 9.129 92/02/15 21:13:08 hines * if bison used compile with -DBISON=1 * * Revision 9.128 92/02/05 14:47:56 hines * saber warning free * FUNCTION made global for use by other models. #define GLOBFUNC 1 * * Revision 9.127 92/02/05 12:32:05 hines * creates setdata_suffix(x) to allow use of data when functions called * from hoc. * * Revision 9.126 92/02/05 08:34:09 hines * NEURON {POINTER ...} allows a model to connect to external variables * #includes in nparout moved to beginning of defslist so crucial fields in * section structures not defined into nonsense. * * Revision 9.125 92/01/28 14:08:00 hines * fix Imakefile * * Revision 9.123 91/12/27 12:29:44 hines * no message when COMPARTMENT does not specify STATE since * it may specify an assigned or parameter. Note that * this statement is irrelevant but it is necessary for modlunit * * Revision 9.122 91/10/28 09:10:19 hines * wathey's improvements. different binary architectures in different * directories. * * Revision 9.121 91/10/01 11:30:13 hines * SUFFIX nothing now really adds nothing (usd to add _) * * Revision 9.120 91/09/16 15:46:15 hines * reorganization of how NEURON variables are declared. * RANGE: definitely range variables, can be param, assigned, or state * GLOBAL: definitely global variables, can be param or assigned * SECTION: not implemented * By default params are global variables. * By default states are range * By default assigned are in p array but not accessible from NEURON * NON-SPECIFIC current not accessible unless specified in RANGE. * * Revision 9.119 91/09/11 11:51:38 hines * extraneous rule in conststmt: removed * * Revision 9.118 91/09/11 11:14:53 hines * bad function number used in multiple kinetic models. * * Revision 9.116 91/08/23 08:30:01 hines * MACHDEP was changed to MACHDEF * * Revision 9.115 91/08/22 17:07:43 hines * for distribution to work on RS6000 * * Revision 9.114 91/08/15 11:18:31 hines * point process calls to point.c in neuron don't use getarg, etc. This * means a change to the calling sequence doesn't necessarily mean a change * to nparout.c * * Revision 9.113 91/08/13 09:17:41 hines * Comments inside strings do not need to be escaped. And they cause warnings * on some machines. * * Revision 9.112 91/08/12 11:35:41 hines * creates a get_loc_suffix(i) function to tell what location and * section of ith index is. * * Revision 9.111 91/08/12 11:34:33 hines * more generic makefile. Change MACHDEF for machine dependent definitions. * * Revision 9.110 91/08/12 09:57:56 hines * set_seed missing in extdef.h * * Revision 9.109 91/07/30 10:22:30 hines * eion, ioni, iono are constants, iion is assigned * * Revision 9.107 91/06/29 08:51:45 hines * left out hparout.o in nmodl.mk * * Revision 9.106 91/06/29 08:45:32 hines * more general units factor and slightly different syntax for conversion * * Revision 9.105 91/06/25 09:02:47 hines * last change broke saber... * * Revision 9.104 91/06/25 08:40:30 hines * makefile fairly generic, no sun4 isms * * Revision 9.103 91/06/25 08:18:48 hines * first attempt at generic makefile, no sun4 isms * * Revision 9.102 91/05/22 13:42:51 hines * last change botched * * Revision 9.101 91/05/22 13:39:24 hines * get modlunit stuff from SRC directory instead of RCS directory. * * Revision 9.100 91/05/06 13:28:01 hines * malloc not properly declared when compiling with turboc * * Revision 9.99 91/04/17 16:15:35 hines * DISCRETE block integrates by delta_indepvar instead of 1.0. * Also delta_indepvar not changed automatically and model() may return * at indepvar at value different from request if break not an integral * value of delta_indepvar. * * Revision 9.98 91/03/18 09:11:45 hines * FORALL i {} loops over all elements of vectors in statements. vector * length must be the same. * * Revision 9.97 91/02/15 13:35:23 hines * allow READ and WRITE of same ionic variable * * Revision 9.96 91/02/08 09:49:26 hines * "nothing" allowed as suffix (auto functions get base filename) * trivial model works since v, t, dt, etc auto created if not declared. * * Revision 9.95 91/01/29 09:16:04 hines * nmodl doesn't create modl_set_dt because multiple mechanisms would make * multiple declarations. * * Revision 9.94 91/01/24 14:00:45 hines * translation error when last token of LOCAL statement was the first token * after the LOCAL statement. Fixed by changing symbols at the parser instead * of the lexical analyser. * * Revision 9.93 91/01/03 08:00:15 hines * some static neuron variables were not declared under some circumstances. * * Revision 9.92 91/01/03 07:55:10 hines * nparout.c version comment moved to beginning of file * * Revision 9.91 91/01/03 07:18:40 hines * stepforce and schedule added to extdef.h * * Revision 9.90 91/01/02 08:00:53 hines * stepforce and schedule added to list of functions which handle * discontinuities. * * Revision 9.89 90/12/14 15:44:24 hines * nmodl: point process working with proper current dimensions. tested with * stim.mod and pascab1.hoc * * Revision 9.88 90/12/14 12:52:35 hines * nmodl: point processes allowed via POINT_PROCESS * * Revision 9.87 90/12/13 11:25:11 hines * calculation of _nstep cast to (int) * * Revision 9.86 90/12/12 18:18:14 hines * FROM index : index is an integer and cast to double wherever it * appears in expressons. It is not cast to int whenever it appears * in intexpr * * Revision 9.85 90/12/12 17:24:04 hines * nmodl: FROM i translates i as double fh.mod works properly * * Revision 9.84 90/12/12 10:06:59 hines * nmodl: GLOBAL allowed in NEURON block * * Revision 9.83 90/12/12 09:02:14 hines * nmodl: nparout allocates the p-array * * Revision 9.82 90/12/12 09:01:29 hines * LOCAL arrays allowed * * Revision 9.81 90/12/12 08:05:47 hines * NMODL: better partition of global and p-array. parameters that are * not explicitly defined become static. * * Revision 9.80 90/12/11 11:23:46 hines * forgot to take care of case where there is no TABLE statement * * Revision 9.79 90/12/11 10:55:29 hines * TABLE works with hocmodl * * Revision 9.78 90/12/10 16:56:48 hines * TABLE allowed in FUNCTION and PROCEDURE * * Revision 9.76 90/12/07 09:27:32 hines * new list structure that uses unions instead of void *element * * Revision 9.75 90/12/05 11:03:38 hines * forgot to add pindex to s->varnum to get index into parray for specific index. * * Revision 9.74 90/12/04 13:08:30 hines * kept calling initmodel from model. Now use hoc_pindepindex * * Revision 9.73 90/12/04 12:00:24 hines * model version displayed only as comment in generated c file * format of plot lines for scalar in .var file is * name nl vindex pindex 1 nl * for vector with specific index: * name[index] vindex pindex 1 * for vector without index * name[size] vindex pindex size * * Revision 9.72 90/11/30 13:10:07 hines * dcurdv calculated for ionic currents. * * Revision 9.71 90/11/30 08:22:24 hines * modl_set_dt should only be created for time dependent models * * Revision 9.70 90/11/28 15:35:18 hines * much work on case when ion is a state * * Revision 9.69 90/11/28 12:54:22 hines * ion variables do not all appear in the hoc name list. * diam understood * * Revision 9.68 90/11/28 09:12:07 hines * location where we are checking for STADYSTATE may not be a SYMBOL * * Revision 9.67 90/11/27 12:10:46 hines * bug in bnd introduced by change to partial * * Revision 9.66 90/11/27 10:47:49 hines * allow multiple partial equations within a partial block * * Revision 9.65 90/11/26 09:14:06 hines * merge didn't recognize units * * Revision 9.64 90/11/26 08:16:14 hines * external functions of type EXTDEF3 get two extra arguments. * The first arg is a pointer to _reset which should be set by the * function upon the occurence of a discontinuity. * The second arg is a pointer to a double which may be used by the * function to store information to help determine if a discontinuity * has occurred. init.c gives a list of these functions. * * Revision 9.63 90/11/23 15:07:22 hines * factor calculation using units.c of model * * Revision 9.62 90/11/23 10:33:18 hines * steadystate in BREAKPOINT block had failed to allocate delta_t * * Revision 9.61 90/11/23 10:01:50 hines * STEADYSTATE of kinetic and derivative blocks * * Revision 9.60 90/11/21 10:47:17 hines * _ninits is first argument in call to integrators * * Revision 9.59 90/11/21 08:41:10 hines * merge allows BREAKPOINT and PARAMETER. makefile merge works * * Revision 9.58 90/11/20 17:24:22 hines * CONSTANT changed to PARAMETER * CONSTANT now refers to variables that don't get put in .var file * * Revision 9.57 90/11/20 16:04:27 hines * EQUATION changed to BREAKPOINT * STEADYSTATE keyword added, EQUATION keyword still exists * * Revision 9.56 90/11/15 16:16:02 hines * unit parentheses for numbers and functions were not being removed. * * Revision 9.55 90/11/15 16:05:23 hines * units definition syntax is (unit) (unit) * * Revision 9.54 90/11/13 15:49:45 hines * allow function definitions and function definition arguments to * have units specifications. Also numbers can have units specifications. * * Revision 9.53 90/11/13 13:10:21 hines * nmodl: cachan works pretty well. ions generating current works. * * Revision 9.52 90/11/10 15:45:00 hines * nmodl: uses new NEURON { USEION ... format * passive.c works * * Revision 9.51 90/11/02 09:12:02 hines * TABLE keyword added. For now it is translated just as FUNCTION * * Revision 9.50 90/11/02 08:31:52 hines * Allow UNITS block and make a units defintion scale factor a static * variable so that it doesn't have to appear in the var file. eg. * UNITS { FARADAY = 96520 (coul) } * * Revision 9.49 90/11/02 07:01:15 hines * works better. Problem is that conditional macros cannot be used * in explicit target. * * Revision 9.48 90/11/02 06:59:36 hines * new way of specifying NEURON info. Keywords are * NEURON SUFFIX CURRENT NEED GET SET * * Revision 9.47 90/11/01 15:21:19 hines * SOLVE procedure allowed. The procedure needs to return an error code * with a VERBATIM statement * * Revision 9.46 90/10/30 14:29:23 hines * calc_dt is gone. Not needed because due to scopfit, dt needs to be * calculated at every break point. * _reset no longer used to say that dt has changed. The integrator will * have to check that itself. * * Revision 9.45 90/10/30 13:56:57 hines * derivative blocks (this impacts kinetic and sens as well) now return * _reset which can be set with RESET statement. _reset is static in the * file and set to 0 on entry to a derivative or kinetic block. * * Revision 9.44 90/10/30 10:25:16 hines * modl: saber warning free except for ytab.c and lex.c * * Revision 9.43 90/10/30 10:21:30 hines * ytab.o was not placed in proper directory * * Revision 9.42 90/10/30 10:01:06 hines * hmodl saber warning free and test.mod works * * Revision 9.41 90/10/30 08:37:13 hines * saber warning free except for ytab.c and lex.c * * Revision 9.40 90/10/30 08:07:07 hines * nmodl: Passive.mod working with index vectors. No longer copying * doubles. Just copying two pointers. * * Revision 9.39 90/10/30 07:32:47 hines * modl, nmodl, hmodl, smodl objects appear in different directories * but sources and archive files come from SRC and RCS respectively * * Revision 9.38 90/10/29 18:30:47 hines * restore after accidental erasure * * Revision 9.37 90/10/15 13:08:40 hines * parout separated into parout for modl, hparout for hmodl nparout for nmodl * * Revision 9.35 90/10/15 12:13:05 hines * mistake with checkin * * Revision 9.34 90/10/15 11:47:09 hines * hmodl: use _p[] * * Revision 9.33 90/10/11 15:45:06 hines * bugs fixed with respect to conversion from pointer vector to index vector. * * Revision 9.32 90/10/08 14:12:58 hines * index vector instead of pointer vector for slist and dlist * * Revision 9.31 90/10/08 11:34:06 hines * simsys prototype * * Revision 9.30 90/09/10 14:12:00 hines * extdef2.h added to makefile and checked in * * Revision 9.29 90/09/10 14:09:18 hines * certain functions specified in extdef2.h can have arguments which are * pointers to functions and pointers to vectors. * * Revision 9.28 90/09/09 17:28:29 hines * merge the summer's work at nbsr into modl * * Revision 9.27 90/09/05 07:08:26 hines * changed spar_rhs to modl_rhs in kinetic.c so that it would not * conflict with hoc sparse matrix. The only externs is sparse.c * are now _getelm sparse modl_rhs * * Revision 9.26 90/08/30 11:29:07 hines * units computations removed and can link with saber-c * * Revision 9.25 90/08/30 11:28:24 hines * units computations removed * * Revision 9.24 90/08/17 08:45:00 hines * mistake on last checkin * * Revision 9.23 90/08/17 08:39:30 hines * no more modltype for double scalars * * Revision 9.22 90/08/17 08:15:02 hines * HMODL change define from HOC to HMODL, ensure all .c files compiled * * Revision 9.21 90/08/17 08:13:46 hines * flux input to array state missing a ) * * Revision 9.20 90/08/15 15:17:03 hines * need to pass error value from crank back through the * block called by SOLVE. * * Revision 9.19 90/08/07 15:36:45 hines * forgot name of mechanism. Also append suffix to all range names * * Revision 9.18 90/08/07 15:36:03 hines * computation of rhs was bad * * Revision 9.17 90/08/07 08:43:58 hines * functions and procedures interfaced to NMODL and HMODL * * Revision 9.16 90/08/02 08:58:49 hines * NMODL can use more than one mechanism. Integrators that use ninits and * reset will not work, though. * * Revision 9.15 90/08/01 07:48:49 hines * repair HOC portion after all the errors introduced by NMODL * * Revision 9.14 90/07/31 17:03:54 hines * NMODL getting close. Compiles but multiple .mod files cause * multiple definitions. * * Revision 9.13 90/07/30 14:37:20 hines * NMODL looks pretty good. Ready to start testing. Have not yet tried * to compile the .c file. * * Revision 9.12 90/07/30 12:38:04 hines * wrong name for ASSIGNED * * Revision 9.11 90/07/30 11:51:18 hines * NMODL getting better, almost done * * Revision 9.10 90/07/27 13:58:11 hines * nmodl handles declarations about right for first pass at this. * * Revision 9.9 90/07/26 09:25:10 hines * beginning interface to NEURON * new keywords are PARAMETER and CURRENT * * Revision 9.8 90/07/26 07:58:45 hines * interface modl to hoc and call the translator hmodl * * Revision 9.7 90/07/21 11:36:18 hines * allow more than one reactant on -> reaction * fix bug where wrong reactant index used in constructing term. * * Revision 9.6 90/07/18 08:15:44 hines * PARAMETER is synonym for CONSTANT * Distinguishing them is necessary for NEURON since PARAMETER's can * vary with position on the neuron. * * Revision 9.5 90/07/18 08:00:21 hines * turn off units. * define for arrays now (p + n) instead of &p[n]. This allows the c file * to have arrays that look like a[i] instead of *(a + i). * * Revision 9.4 90/06/04 08:23:27 mlh * extend exponents from both expressions dimensionless to * allowing exponent to be positive integer. * * Revision 9.3 90/06/01 11:02:07 mlh * checks for conformability of units but does not check for * correct conversion factors. * in x^y, both x and y must be dimensionless * * Revision 9.2 90/05/30 17:01:16 mlh * not working yet, just adding files administratively * * Revision 8.30 90/04/09 08:41:42 mlh * implicit method for derivative blocks (allows mixed equations also). * The solve statement must precede the derivative block * * Revision 8.29 90/04/04 14:15:00 mlh * when multiple sparse models were called, MATELM was defined only * once and getelm was multiply declared. Now fixed. * * Revision 8.28 90/04/03 07:49:12 mlh * typo in previous change. Due to nature of RCS on nbsr, it is unfortunately * necessary to check things back in before testing. * * Revision 8.27 90/04/03 07:47:02 mlh * for turbo-c defs.h stuff must appear after inclusion of scoplib.h * This is done by now saving defs.h stuff in defs_list and printing * it in cout.c. Note that each item is type VERBATIM so that there * is no prepended space. * * Revision 8.26 90/02/15 10:11:54 mlh * defs.h no longer included. #defines come from parraycount during * handling of .var file. Thsi handling must be before putting info * in .c file * * Revision 8.25 90/02/15 08:57:59 mlh * first check for .mrg file and translate if it exists * if not the check for .mor file and translate that. * This is done if there is only one argument. * If two arguments then use first as basename and * second as input file * print message about what it is doing * * Revision 8.24 90/02/07 10:23:27 mlh * It is important that blocks for derivative and sensitivity also * be declared static before their possible use as arguments to other * functions and that their body also be static to avoid multiple * declaration errors. * * Revision 8.23 90/01/29 14:07:37 mlh * simplex is a nonlinear method * * Revision 8.22 90/01/23 16:11:09 mlh * delta_t is calculated for the first two calls after * a call to initmodel(). This is because the breakpoint * interval can change aftera the first call to model(). * The implementation is accomplished by _calc_dt=2 * in initmodel() and _calc_dt-- when _calc_dt is nonzero * in model() * * Revision 8.21 90/01/19 07:38:07 mlh * _modl_cleanup() called by abort_run() * * Revision 8.20 90/01/18 11:46:34 mlh * SOLVEFOR statement added * syntax is * blocktype blockname [SOLVEFOR name, name, ...] {statment} * where blocktype is KINETIC, NONLINEAR, or LINEAR * Only the states in the SOLVEFOR statement are solved * in that block. If the statement is not present then * all states are solved that appear in that block. * * Revision 8.19 90/01/18 08:14:22 mlh * serious error in calculating p-array index for * plot variables in .var file. * Fixed by using symbol->varnum to hold the p-index. * * Revision 8.18 90/01/16 11:06:28 mlh * error checking and cleanup after error and call to abort_run() * * Revision 8.17 90/01/03 16:13:44 mlh * discrete array variables had their for loops switched. * * Revision 8.16 89/12/18 07:58:23 mlh * Fixed problem in .var file in which x-axis array variable's dimension * was 1 too large. * * Revision 8.15 89/12/15 10:11:02 mlh * newton's last arg changed to vector of double pointers. * For nonlinear equations dlist holds the doubles and * pdlist points to them individually. * * Revision 8.14 89/11/21 08:18:46 mlh * More reliable method for ensuring that solve for loop ends up exactly * at the final time value. * * Revision 8.13 89/11/21 07:37:11 mlh * _calc_dt used in scopcore and therefore must be declared even for * time independent models. * * Revision 8.12 89/11/17 16:08:28 mlh * _ninits tells how many times initmodel() is called. Used by * scopmath routines that need to know when to self_initialize. * * Revision 8.11 89/11/17 15:12:43 nfh * Changed modl_version string printed by SCoP to read: "Language version..." * * Revision 8.10 89/11/14 16:38:00 mlh * _reset set to true whenever initmodel is called and whenever _calc_dt * is true * * Revision 8.9 89/11/13 15:17:48 mlh * _called_init changed to _calc_dt and made global so * that scop can cause dt to be recomputed on an * extend run command * * Revision 8.8 89/11/01 10:21:17 mlh * Three changes * consist moved after solvehandler to avoid warning that delta_indep is * >> undeclared. * Warning given if state is assigned a value in a DERIVATIVE block * identical names in nested LOCAL statements declared incorrectly. * >> The problem was fixed by not allowing extra _l prepended to * >> an already local variable. * * Revision 8.7 89/10/30 15:04:34 mlh * error message when no derivative equations in DERIVATIVE block * * Revision 8.6 89/10/27 15:44:25 mlh * initqueue() called in initmodel() when PUTQ or GETQ used. * * Revision 8.5 89/10/25 13:48:15 mlh * PUTQ and GETQ implemented * * Revision 8.4 89/10/25 13:43:47 mlh * Bug with discrete models in that delta_indep is used * Fixed by generating the proper line only when type is DERF * * Revision 8.3 89/10/11 08:43:27 mlh * _reset apparently bein declared elsewhere * * Revision 8.2 89/10/11 08:35:29 mlh * generate modl_version string in .c file * declare _reset=1 * * Revision 8.1 89/09/29 16:26:09 mlh * ifdef for VMS and SYSV and some fixing of assert * * Revision 8.0 89/09/22 17:27:06 nfh * Freezing * * Revision 7.2 89/09/07 07:45:48 mlh * 1) a scop independent variable may be a constant and an independent * 2)was failing to prevent multiple declarations involveing the SWEEP variable * 3) was not initializing time after match * 4) many bugs in handling exact for loop of t to the break point * >> * * * Revision 7.1 89/09/05 08:10:09 mlh * ensure an integer number of steps/break * allow us to deal easily with lists of pointers to item pointers * COMPARTMENT keyword for KINETIC block * * Revision 7.0 89/08/30 13:32:43 nfh * Rev 7 is now Experimental; Rev 6 is Testing * * Revision 6.3 89/08/24 12:08:11 mlh * failed to declare reprime(), make lint free * * Revision 6.2 89/08/23 12:03:22 mlh * kinetic reaction may involve stepped and independent (sweeped) variable * * Revision 6.1 89/08/23 10:32:18 mlh * derivative variables in .var file have names like var' instead of Dvar * * Revision 6.0 89/08/14 16:27:22 nfh * Rev 6.0 is latest of 4.x; now the Experimental version * * Revision 4.8 89/08/12 11:04:13 mlh * In hierarchical models, CONSTANT and ASSIGNED can be promoted to STATE * * Revision 4.7 89/08/11 09:57:29 mlh * simultaneous nonlinear equations allowed in DERIVATIVE block * CONSTANT and ASSIGNED variables can appear as terms in reactions * in a KINETIC block * * Revision 4.6 89/08/07 15:35:37 mlh * freelist now takes pointer to list pointer and 0's the list pointer. * Not doing this is a bug for multiple sens blocks, etc. * * Revision 4.5 89/08/05 11:38:45 mlh * axis units info now in .var file * units for higher order derivatives auto generated * .var syntax for higher order derivative states now a:b * * Revision 4.4 89/08/01 07:35:47 mlh * DEPENDENT keyword changed to ASSIGNED * * Revision 4.3 89/07/31 07:56:26 mlh * Slight problem with error messages. Now missing partial equation in PARTIAL * block says DEL2 instead of DEL * * Revision 4.2 89/07/27 13:28:18 mlh * crank calling sequence sends indepsym as a sentinal value * ugh! * * Revision 4.1 89/07/25 19:22:22 mlh * fixed error in copying string into too small a space in * section handling higher order derivatives. * * Revision 4.0 89/07/24 17:03:53 nfh * Freezing rev 3. Rev 4 is now Experimental * * Revision 3.10 89/07/21 09:28:21 mlh * Discrete equitions evaluated at time given by independent variable * in the sense that the state on the left hand side refers to state(t) * and explicit dependence on t works naturally. * * Revision 3.9 89/07/19 15:05:44 mlh * pass t by value introduces bug, return to version before that. * * Revision 3.8 89/07/18 15:29:14 mlh * integrators now are passed value of time instead of pointer to time * * Revision 3.7 89/07/18 11:55:29 mlh * first_time removed and MODEL_LEVEL used for declaration precedence * * Revision 3.6 89/07/12 16:34:06 mlh * 2nd optional argument gives input file. First arg is prefix to .var * and .c files (and .mod input file if 2nd arg not present). * * Revision 3.5 89/07/12 12:24:03 mlh * state@1 now refers to state value at end of previous step * state@0 is a syntax error * * Revision 3.4 89/07/11 19:32:26 mlh * missing ) from previous checkin * * Revision 3.3 89/07/11 19:30:00 mlh * Bug in which initial condition could not be a STEPPED variable is fixed * * Revision 3.2 89/07/11 16:56:58 mlh * remove p array from calling sequence of crank * * Revision 3.1 89/07/07 16:55:24 mlh * FIRST LAST START in independent SWEEP higher order derivatives * * Revision 1.1 89/07/07 16:25:06 mlh * Initial revision * * Revision 3.1 89/07/07 08:57:37 mlh * major revision * * Revision 1.2 89/07/06 15:35:04 mlh * inteface with version.c * * Revision 1.1 89/07/06 15:27:11 mlh * Initial revision * */ char *RCS_version = "$Revision: 1098 $"; char *RCS_date = "$Date: 2005-10-04 22:55:37 +0200 (Tue, 04 Oct 2005) $"; mod2c-8.2.2/test/000077500000000000000000000000001425457616700135275ustar00rootroot00000000000000mod2c-8.2.2/test/validation/000077500000000000000000000000001425457616700156615ustar00rootroot00000000000000mod2c-8.2.2/test/validation/CMakeLists.txt000066400000000000000000000047511425457616700204300ustar00rootroot00000000000000# Copyright (c) 2016, Blue Brain Project # 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. Neither the name of the copyright holder nor the names of its contributors # may 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 HOLDER 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. include(TestScriptUtils) set(TEST_LABEL validation) add_test_class(validation) set(MOD2CFILTER "perl ${CMAKE_CURRENT_SOURCE_DIR}/filter_mod2c_output.pl") configure_file("test_mod2c.in" ${CMAKE_CURRENT_BINARY_DIR}/test_mod2c @ONLY) set(MOD2CFILTER "perl ${CMAKE_CURRENT_SOURCE_DIR}/filter_mod2c_output.pl -DNRNBBCORE=1") configure_file("test_mod2c.in" ${CMAKE_CURRENT_BINARY_DIR}/test_mod2c_core @ONLY) set(TEST_ENVIRONMENT "MODLUNIT=${CMAKE_BINARY_DIR}/share/mod2c/nrnunits.lib") foreach(mod2c "mod2c_core") set(test_data "${CMAKE_CURRENT_SOURCE_DIR}/${mod2c}") file(GLOB test_mods RELATIVE "${test_data}/mod" "${test_data}/mod/*.mod") foreach(modfile ${test_mods}) set(mod ${modfile}) string(REGEX REPLACE "\\.mod$" "" mod "${modfile}") set(TEST_ARGS ${CMAKE_BINARY_DIR}/bin/${mod2c} ${test_data}/mod/${mod}.mod ${test_data}/cpp/${mod}.cpp) add_test_script("${mod2c}-${mod}" "${CMAKE_CURRENT_BINARY_DIR}/test_${mod2c}" "/bin/bash") endforeach() endforeach() mod2c-8.2.2/test/validation/README000066400000000000000000000004721425457616700165440ustar00rootroot00000000000000The .mod files under mod/ and the pre-converted .c files in this test directory are present only for mod2c validation purposes. They should not be regarded as reflecting the current state of production modules. Update: nocmodl_core reference .c files updated to reflect changes from patch addressing [CBLUR-57]. mod2c-8.2.2/test/validation/filter_mod2c_output.pl000066400000000000000000000024401425457616700222070ustar00rootroot00000000000000#!/usr/bin/perl -w # Filter mod2c/mod2c_core output for comparison purposes. # 1) rewrites #include lines # 2) performs cpp preprocessing # 3) tokenizes (naively) to one item per line # 4) remove path string in "help ..." # usage: filter_mod2c_output.pl [additional CPP options...] < mechanism.c # filter_mod2c_output.pl [additional CPP options...] -- mechanism.c use File::Temp qw/tempfile/; my @cpp_args=qw/-nostdinc -P/; while (@ARGV) { my $a=shift @ARGV; next if $a eq '--'; push @cpp_args,$a; } my ($fh,$fname) = tempfile(UNLINK=>1); while (<>) { s/#\s*include\s*"([^"]*)"/INCLUDE("$1")/g; s/#\s*include\s*<([^>]*)>/INCLUDE_SYSTEM("$1")/g; $fh->print($_); } $fh->close(); open(CPP,"-|","cpp",@cpp_args,$fname) or die "failed to invoke cpp\n"; print map {s/"help .*"/"help XXX"/; "$_\n"} tokenize($_) while ; close(CPP); sub tokenize { my @ts=(); while (/\s*( (?['"]) (\\. | [^\\])*? (\g{q}|$) # single or double quoted string literal | [\w\d\$]+ # numeric literal or identifier | [(){},;\?:\[\]] # delimiter or unambiguous single character operator | [^\s'"\w\d\$(){},;\?:\[\]]+ # sequence of punctuation otherwise not handled )\s*/gx) { push @ts,$1; } return @ts; } mod2c-8.2.2/test/validation/mod/000077500000000000000000000000001425457616700164405ustar00rootroot00000000000000mod2c-8.2.2/test/validation/mod/NaSm.mod000066400000000000000000000030061425457616700177760ustar00rootroot00000000000000TITLE A slow Sodium current COMMENT Used in Role of a Striatal Slowly Inactivating Potassion Current in Short-term Facilitation of Corticostriatal Inputs" A computer Simulation Study" (Mahon et al. 2000) Implemented by Kevin M. Biddell kevin.biddell@gmail.com 7/17/06 NOTE: 1S=1mho Neuron wants the units in mhos not millisiemens, please note the conversion! ENDCOMMENT UNITS { (mA) = (milliamp) (mV) = (millivolt) } NEURON { SUFFIX NaSm USEION na WRITE ina RANGE gnasmbar, gnasm, minf, mtau } INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)} PARAMETER { ena = 40 (mV) gnasmbar= 0.00011 (mho/cm2) :0.11mS Etemp = 21 :delord correspondence 11/15/06 Vsm = -16.0 ksm = 9.4 tom = 637.8 Vtm = -33.5 ktm = 26.3 } STATE { m } ASSIGNED { v (mV) ina (mA/cm2) celsius (degC) minf mtau gnasm } BREAKPOINT { SOLVE states METHOD cnexp gnasm = gnasmbar*m ina = gnasm*(v - ena) } UNITSOFF INITIAL { rates(v) m= minf } DERIVATIVE states { :Computes states variable m at the current v and dt. rates(v) m' = ( minf - m ) / mtau } PROCEDURE rates(v) { :Computes rate and other constants at current v. Call once from HOC to initialize inf at resting v. LOCAL q10,tadj q10 = 2.5 tadj=q10^((celsius-Etemp)/10) minf=1/(1+exp(-(v-Vsm)/ksm)) mtau=tom/(exp(-(v-Vtm)/ktm)+exp((v-Vtm)/ktm))/tadj } UNITSON mod2c-8.2.2/test/validation/mod/Nap.mod000066400000000000000000000034061425457616700176620ustar00rootroot00000000000000TITLE nap NEURON { SUFFIX nap USEION na READ ena WRITE ina RANGE gbar, timestauh, timestaum, shifttaum, shifttauh, thegna RANGE minf, mtau :, hinf, mtau, htau } PARAMETER { gbar = .0052085 (mho/cm2) :q10m=3.1 :q10h=2.3 timestauh=1 timestaum=1 shifttaum=1 shifttauh=1 eNa = 55 (mV) :Golomb et al. ena (mV) : must be explicitly def. in hoc celsius (degC) v (mV) } UNITS { (mA) = (milliamp) (mV) = (millivolt) (pS) = (picosiemens) (um) = (micron) } ASSIGNED { ina (mA/cm2) thegna (mho/cm2) minf :hinf mtau (ms) :htau (ms) } STATE { m } : hier eigener Befehl UNITSOFF BREAKPOINT { SOLVE states METHOD cnexp mtau = 1 minf = (1/(1+exp(-(v+52.3)/6.8))) :midpoint -56.3, slope 7.4 :trates(v) :Temparaturabhaengigkeit mit modellieren??? thegna =gbar*m :thegna = gbar*m*m*h ina = thegna * (v - eNa) } INITIAL { :trates(v) mtau = 1 minf = (1/(1+exp(-(v+52.3)/6.8))) :midpoint - 52.3 slope 6.8 5.5 m=minf :h=hinf } DERIVATIVE states { :trates(v) mtau = 1 minf = (1/(1+exp(-(v+52.3)/6.8))) :midpoint - 52.3 (47) slope 6.8 m' = (minf-m)/mtau :h' = (hinf-h)/htau } PROCEDURE trates(vm) { :LOCAL qm,qh,f1,f2,alphah :qm=q10m^((celsius-24)/10) :qh=q10h^((celsius-24)/10) :f1=1/(1+exp(-(v-7.63)/28.47))+0.01 :f2=62.82/(1+exp((v+37.02)/5.27))+3.78 :mtau=f1*f2/qm*timestaum+shifttaum :minf = (1/(1+exp(-(v+31.4)/8.8)))^0.5 :hinf = 1/(1+exp((v+72)/3.7)) :alphah=0.0021/(1+exp((v+65.77)/4.32)) :mtau = 1 :minf = (1/(1+exp(-(v+41)/3))) :htau = hinf/(qh*alphah)*timestauh+shifttauh } : hier eigener Befehl UNITSON mod2c-8.2.2/test/validation/mod/NapDA.mod000077500000000000000000000021361425457616700200710ustar00rootroot00000000000000: Persistent Na+ channel under D1 : from Durstewitz & Gabriel (2006), Cerebral Cortex NEURON { SUFFIX NapDA USEION na WRITE ina RANGE gNapbar, gna, ena } UNITS { (mA) = (milliamp) (mV) = (millivolt) } PARAMETER { gNapbar= 0.0022 (mho/cm2) <0,1e9> ena = 55 (mV) } ASSIGNED { v (mV) ina (mA/cm2) gna (mho/cm2) } STATE { m h } INITIAL { m = malf(v)/(malf(v)+mbet(v)) h = half(v)/(half(v)+hbet(v)) } BREAKPOINT { SOLVE states METHOD derivimplicit gna = gNapbar*m*h ina = gna*(v-ena) } DERIVATIVE states { m' = (1-m)*malf(v)-m*mbet(v) h' = ((1-h)*half(v)-h*hbet(v))/2.0 } UNITSOFF FUNCTION malf(v(mV)) (/ms) { LOCAL va va=v+12 if (fabs(va)<1e-04) { malf= -0.2816*(-9.3 - va*0.5) } else { malf = -0.2816*va/(-1+exp(-va/9.3)) } } FUNCTION mbet(v(mV)) (/ms) { LOCAL vb vb=v-15 if (fabs(vb)<1e-04) { mbet = 0.2464*(6 - vb*0.5) } else { mbet = 0.2464*vb/(-1+exp(vb/6)) } } FUNCTION half(v(mV)) (/ms) { half= 2.8e-5*(exp(-(v+42.8477)/4.0248)) } FUNCTION hbet(v(mV)) (/ms) { hbet= 0.02/(1+exp(-(v-413.9284)/148.2589)) } UNITSON mod2c-8.2.2/test/validation/mod/NapIn.mod000066400000000000000000000020271425457616700201470ustar00rootroot00000000000000TITLE nap NEURON { SUFFIX napIn USEION na READ ena WRITE ina RANGE gbar, thegna, htau RANGE minf, mtau, hinf } PARAMETER { gbar = .0052085 (mho/cm2) htau = 15 (ms) eNa = 55 (mV) :Golomb et al. ena (mV) : must be explicitly def. in hoc celsius (degC) v (mV) } UNITS { (mA) = (milliamp) (mV) = (millivolt) (pS) = (picosiemens) (um) = (micron) } ASSIGNED { ina (mA/cm2) thegna (mho/cm2) minf hinf mtau (ms) } STATE { m h} : hier eigener Befehl UNITSOFF BREAKPOINT { SOLVE states METHOD cnexp trates(v) :Temparaturabhaengigkeit mit modellieren??? thegna =gbar*m*h :hier geaendert ina = thegna * (v - eNa) } INITIAL { trates(v) m=minf h=hinf } DERIVATIVE states { trates(v) m' = (minf-m)/mtau h' = (hinf-h)/htau } PROCEDURE trates(vm) { mtau = 1 minf = 1/(1+exp(-(v+52.3)/6.8)) hinf = 1/(1+exp((v+48)/10.0)) : hier aendern } : hier eigener Befehl UNITSON mod2c-8.2.2/test/validation/mod/Nap_E.mod000066400000000000000000000032721425457616700201270ustar00rootroot00000000000000:Comment : mtau deduced from text (said to be 6 times faster than for NaT) :Comment : so I used the equations from NaT and multiplied by 6 :Reference : Modeled according to kinetics derived from Magistretti & Alonso 1999 : Adapted by Werner Van Geit @ BBP, 2015 (with help from M.Hines): : channel detects TTX concentration set by TTXDynamicsSwitch.mod NEURON { SUFFIX Nap_E USEION na READ ena WRITE ina USEION ttx READ ttxo, ttxi VALENCE 1 RANGE gNap_Ebar, gNap_E, ina } UNITS { (S) = (siemens) (mV) = (millivolt) (mA) = (milliamp) } PARAMETER { gNap_Ebar = 0.00001 (S/cm2) } ASSIGNED { ttxo (mM) ttxi (mM) v (mV) ena (mV) ina (mA/cm2) gNap_E (S/cm2) mInf mTau mAlpha mBeta hInf hTau hAlpha hBeta } STATE { m h } BREAKPOINT { SOLVE states METHOD cnexp gNap_E = gNap_Ebar*m*m*m*h ina = gNap_E*(v-ena) } DERIVATIVE states { if (ttxi == 0.015625 && ttxo > 1e-12) { mInf = 0.0 mTau = 1e-12 hInf = 1.0 hTau = 1e-12 } else { rates() } m' = (mInf-m)/mTau h' = (hInf-h)/hTau } INITIAL{ if (ttxi == 0.015625 && ttxo > 1e-12) { mInf = 0.0 mTau = 1e-12 hInf = 1.0 hTau = 1e-12 } else { rates() } m = mInf h = hInf } PROCEDURE rates(){ UNITSOFF mInf = 1.0/(1+exp((v- -52.6)/-4.6)) if(v == -25){ v = v + 0.0001 } mAlpha = (0.182 * (v- -25))/(1-(exp(-(v- -25)/9))) mBeta = (0.124 * (-v -25))/(1-(exp(-(-v -25)/9))) mTau = 6 * 1/(mAlpha + mBeta) if(v == -50){ v = v + 0.0001 } hAlpha = (0.00001 * (v- -50))/(1-(exp(-(v- -50)/13))) if(v == -75){ v = v+0.0001 } hBeta = (0.00001 * (-v - 75))/(1-(exp(-(-v - 75)/13))) hInf = 1.0/(1+exp((v- -48.8)/10)) hTau = (1/(hAlpha + hBeta)) UNITSON }mod2c-8.2.2/test/validation/mod/Nap_No.mod000077500000000000000000000027301425457616700203200ustar00rootroot00000000000000TITLE Nap_No.mod persistent sodium current COMMENT This is the original Hodgkin-Huxley treatment for the set of sodium, potassium, and leakage channels found in the squid giant axon membrane. Some parameters have been changed to correspond to McIntyre and Grill (2002) "Extracellular stimulation of central neurons" Author: Balbi ENDCOMMENT UNITS { (mA) = (milliamp) (mV) = (millivolt) (S) = (siemens) } NEURON { SUFFIX Nap_No USEION na READ ena WRITE ina RANGE gnamax, gna RANGE pinf, ptau } PARAMETER { gnamax = 0.01 (S/cm2) <0,1e9> } STATE { p } ASSIGNED { v (mV) ena (mV) gna (S/cm2) ina (mA/cm2) pinf ptau (ms) } BREAKPOINT { SOLVE states METHOD cnexp gna = gnamax*p*p*p ina = gna*(v - ena) } INITIAL { rates(v) p = pinf } DERIVATIVE states { rates(v) p' = (pinf-p)/ptau } PROCEDURE rates(v(mV)) { :Call once from HOC to initialize inf at resting v. LOCAL alpha, beta, sum UNITSOFF :"p" persistent sodium activation system alpha = 0.0353 * vtrap(-17 - v, 10.2) beta = 0.000883 * vtrap(v + 24, 10) sum = alpha + beta ptau = 1/sum pinf = alpha/sum } FUNCTION vtrap(x,y) { :Traps for 0 in denominator of rate eqns. if (fabs(x/y) < 1e-6) { vtrap = y*(1 - x/y/2) }else{ vtrap = x/(exp(x/y) - 1) } } UNITSON mod2c-8.2.2/test/validation/mod/SynNMDA10_1.mod000066400000000000000000000165201425457616700207370ustar00rootroot00000000000000TITLE kinetic NMDA receptor model COMMENT ----------------------------------------------------------------------------- Kinetic model of NMDA receptors best viewed in Notepad++ =============================== 10-state gating model: Kampa et al. (2004) J Physiol U -- Cl -- O \ | \ \ \ | \ \ UMg -- ClMg - OMg | | D1 | | \ | | \ | D2 \| \ D1Mg \ | \ | D2Mg ----------------------------------------------------------------------------- Based on voltage-clamp recordings of NMDA receptor-mediated currents in nucleated patches of rat neocortical layer 5 pyramidal neurons (Kampa 2004), this model was fit with AxoGraph directly to experimental recordings in order to obtain the optimal values for the parameters. ----------------------------------------------------------------------------- This mod file does not include mechanisms for the release and time course of transmitter; it should to be used in conjunction with a sepearate mechanism to describe the release of transmitter and tiemcourse of the concentration of transmitter in the synaptic cleft (to be connected to pointer C here). ----------------------------------------------------------------------------- See details of NEURON kinetic models in: Destexhe, A., Mainen, Z.F. and Sejnowski, T.J. Kinetic models of synaptic transmission. In: Methods in Neuronal Modeling (2nd edition; edited by Koch, C. and Segev, I.), MIT press, Cambridge, 1996. Written by Bjoern Kampa in 2004 ----------------------------------------------------------------------------- These modifications are made by Keivan Moradi 2007 to 2012: - Release process modeled with an internal alpha function in order to make it compatible with NetCon onbject, and therefore does not require an external release mechanism. - Unit of g changed from pS to uS to make the synaptic weights compatible with NEURON's internal methods of modeling synapses (e.x. exp2syn) - gmax is set to 50 Johnson & Ascher, 1990 - rate constant units changed from (/uM /ms) to (/mM /ms) to remove the annoying coefficients - valence of Mg is +2. Why it is -2 here? ----------------------------------------------------------------------------- ENDCOMMENT INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)} NEURON { POINT_PROCESS NMDA10_1 RANGE T_max, T, tau, tRel, Erev, synon RANGE U, Cl, D1, D2, O, UMg, ClMg, D1Mg, D2Mg, OMg RANGE g, gmax, rb, rmb, rmu, rbMg,rmc1b,rmc1u,rmc2b,rmc2u RANGE rmd1b,rmd1u,rmd2b,rmd2u GLOBAL mg, Rb, Ru, Rd1, Rr1, Rd2, Rr2, Ro, Rc, Rmb, Rmu GLOBAL RbMg, RuMg, Rd1Mg, Rr1Mg, Rd2Mg, Rr2Mg, RoMg, RcMg GLOBAL Rmd1b,Rmd1u,Rmd2b,Rmd2u GLOBAL Rmc1b,Rmc1u,Rmc2b,Rmc2u GLOBAL valence, memb_fraction NONSPECIFIC_CURRENT i } UNITS { (nA) = (nanoamp) (mV) = (millivolt) (pS) = (picosiemens) (uS) = (microsiemens) (umho) = (micromho) (mM) = (milli/liter) (uM) = (micro/liter) } PARAMETER { Erev = 0 (mV) : reversal potential gmax = 50 (pS) : maximal conductance mg = 1 (mM) : external magnesium concentration valence = -2 : parameters of voltage-dependent Mg block memb_fraction = 0.8 : alpha function formalism tau = .3 (ms) <1e-9,1e9> T_max = 1.5 (mM) : maximum concentration of neurotransmitter : Rates Rb = 10 (/mM /ms) : binding Ru = 5.6e-3 (/ms) : unbinding Ro = 10e-3 (/ms) : opening Rc = 273e-3 (/ms) : closing Rd1 = 2.2e-3 (/ms) : fast desensitisation Rr1 = 1.6e-3 (/ms) : fast resensitisation Rd2 = 0.43e-3 (/ms) : slow desensitisation Rr2 = 0.5e-3 (/ms) : slow resensitisation Rmb = 0.05 (/mM /ms) : Mg binding Open Rmu = 12800e-3 (/ms) : Mg unbinding Open Rmc1b = 0.00005 (/mM /ms) : Mg binding Closed Rmc1u = 2.438312e-3 (/ms) : Mg unbinding Closed Rmc2b = 0.00005 (/mM /ms) : Mg binding Closed2 Rmc2u = 5.041915e-3 (/ms) : Mg unbinding Closed2 Rmd1b = 0.00005 (/mM /ms) : Mg binding Desens1 Rmd1u = 2.98874e-3 (/ms) : Mg unbinding Desens1 Rmd2b = 0.00005 (/mM /ms) : Mg binding Desens2 Rmd2u = 2.953408e-3 (/ms) : Mg unbinding Desens2 RbMg = 10 (/mM /ms) : binding with Mg RuMg = 17.1e-3 (/ms) : unbinding with Mg RoMg = 10e-3 (/ms) : opening with Mg RcMg = 548e-3 (/ms) : closing with Mg Rd1Mg = 2.1e-3 (/ms) : fast desensitisation with Mg Rr1Mg = 0.87e-3 (/ms) : fast resensitisation with Mg Rd2Mg = 0.26e-3 (/ms) : slow desensitisation with Mg Rr2Mg = 0.42e-3 (/ms) : slow resensitisation with Mg } ASSIGNED { v (mV) : postsynaptic voltage i (nA) : current = g*(v - Erev) g (uS) : conductance T (mM) : neurotransmiter concentration in the cleft tRel (ms) : spiking time of the presynaptic cell synon : turns the synapse on or Off w : weight of synapse rb (/ms) : binding, [glu] dependent rmb (/ms) : blocking V and [Mg] dependent rmu (/ms) : unblocking V and [Mg] dependent rbMg (/ms) : binding, [glu] dependent rmc1b (/ms) : blocking V and [Mg] dependent rmc1u (/ms) : unblocking V and [Mg] dependent rmc2b (/ms) : blocking V and [Mg] dependent rmc2u (/ms) : unblocking V and [Mg] dependent rmd1b (/ms) : blocking V and [Mg] dependent rmd1u (/ms) : unblocking V and [Mg] dependent rmd2b (/ms) : blocking V and [Mg] dependent rmd2u (/ms) : unblocking V and [Mg] dependent } STATE { : Channel states (all fractions) U : unbound Cl : closed D1 : desensitised 1 D2 : desensitised 2 O : open UMg : unbound with Mg ClMg : closed with Mg D1Mg : desensitised 1 with Mg D2Mg : desensitised 2 with Mg OMg : open with Mg } INITIAL { T = 0 synon = 0 tRel = 0 U = 1 } BREAKPOINT { SOLVE kstates METHOD sparse g = w * gmax * O i = g * (v - Erev) } KINETIC kstates { release(t) rb = Rb * T rbMg = RbMg * T rmb = Rmb * mg * exp((1 (/mV) * v-40) * valence * memb_fraction /25) rmu = Rmu * exp((-1 (/mV))*(v-40) * valence * (1-memb_fraction) /25) rmc1b = Rmc1b * mg * exp((1 (/mV) * v-40) * valence * memb_fraction /25) rmc1u = Rmc1u * exp((-1 (/mV))*(v-40) * valence * (1-memb_fraction) /25) rmc2b = Rmc2b * mg * exp((1 (/mV) * v-40) * valence * memb_fraction /25) rmc2u = Rmc2u * exp((-1 (/mV))*(v-40) * valence * (1-memb_fraction) /25) rmd1b = Rmd1b * mg * exp((1 (/mV) * v-40) * valence * memb_fraction /25) rmd1u = Rmd1u * exp((-1 (/mV))*(v-40) * valence * (1-memb_fraction) /25) rmd2b = Rmd2b * mg * exp((1 (/mV) * v-40) * valence * memb_fraction /25) rmd2u = Rmd2u * exp((-1 (/mV))*(v-40) * valence * (1-memb_fraction) /25) ~ U <-> Cl (rb,Ru) ~ Cl <-> O (Ro,Rc) ~ Cl <-> D1 (Rd1,Rr1) ~ D1 <-> D2 (Rd2,Rr2) ~ O <-> OMg (rmb,rmu) ~ UMg <-> ClMg (rbMg,RuMg) ~ ClMg <-> OMg (RoMg,RcMg) ~ ClMg <-> D1Mg (Rd1Mg,Rr1Mg) ~ D1Mg <-> D2Mg (Rd2Mg,Rr2Mg) ~ U <-> UMg (rmc1b,rmc1u) ~ Cl <-> ClMg (rmc2b,rmc2u) ~ D1 <-> D1Mg (rmd1b,rmd1u) ~ D2 <-> D2Mg (rmd2b,rmd2u) CONSERVE U+Cl+D1+D2+O+UMg+ClMg+D1Mg+D2Mg+OMg = 1 } NET_RECEIVE(weight) { if (flag == 0) { tRel = t : resets the alpha function synon = 1 : turns the synapse on. : The alpha function does not require to turn off the synase w = weight } } PROCEDURE release(t(ms)) { T = T_max * (t - tRel) / tau * exp(1 - (t - tRel) / tau) * synon } mod2c-8.2.2/test/validation/mod/SynNMDA10_2.mod000066400000000000000000000114571425457616700207440ustar00rootroot00000000000000TITLE detailed model of glutamate NMDA receptors COMMENT ----------------------------------------------------------------------------- Kinetic model of NMDA receptors =============================== 10-state gating model: Vargas-Caballero & Robinson 2004, J Neurosci. 24(27):6171-6180 D DB | | C0 -- C1 -- C2 -- O -- OB -- CB2 -- CB1 -- CB0 Voltage dependence of Mg2+ block and slow voltage dependent unblok: Vargas-Caballero & Robinson, 2004, J. Neurosci. 24(27):6171-6180 ----------------------------------------------------------------------------- Based on voltage-clamp recordings of NMDA receptor-mediated currents in rat hippocampal slices (Vargas-Caballero & Robinson 2003 J Neurophysiol 89: 2778-2783), this model was fit directly to experimental recordings in order to obtain the optimal values for the parameters (see Vargas-Caballero & Robinson 2004, J. Neurosci. 24(27):6171-6180). ----------------------------------------------------------------------------- See details in: Destexhe, A., Mainen, Z.F. and Sejnowski, T.J. Kinetic models of synaptic transmission. In: Methods in Neuronal Modeling (2nd edition; edited by Koch, C. and Segev, I.), MIT press, Cambridge, 1998, pp 1-25. (electronic copy available at http://cns.iaf.cnrs-gif.fr) Written by Alain Destexhe and Zach Mainen, 1995 ----------------------------------------------------------------------------- These modifications are made by Keivan Moradi 2012: - Release process modeled with an internal alpha function in order to make it compatible with NetCon onbject, and therefore does not require an external release mechanism. - Unit of g changed from pS to uS to make the synaptic weights compatible with NEURON's internal methods of modeling synapses (e.x. exp2syn) - gmax is set to 50 Johnson & Ascher, 1990 - Rate constants are corrected to be like the original article ----------------------------------------------------------------------------- ENDCOMMENT INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)} NEURON { POINT_PROCESS NMDA10_2 RANGE C0, C1, C2, D, O, CB0, CB1, CB2, DB, OB RANGE g, gmax, rb ,rbb, RMgB, RMgU RANGE T_max, T, tau, tRel, Erev, synon GLOBAL mg, Rb, Ru, Rd, Rr, Ro, Rc NONSPECIFIC_CURRENT i THREADSAFE } UNITS { (nA) = (nanoamp) (mV) = (millivolt) (pS) = (picosiemens) (uS) = (microsiemens) (umho) = (micromho) (mM) = (milli/liter) (uM) = (micro/liter) } PARAMETER { Erev = -0.7 (mV) : reversal potential gmax = 50 (pS) : maximal conductance mg = 1 (mM) : external magnesium concentration : Rates Rb = 5000e-3 (/mM /ms) : binding Ru = 5.5e-3 (/ms) : unbinding Rd = 8.4e-3 (/ms) : desensitization Rr = 1.8e-3 (/ms) : resensitization Ro = 46.5e-3 (/ms) : opening Rc = 91.6e-3 (/ms) : closing : alpha function formalism tau = .3 (ms) <1e-9,1e9> T_max = 1.5 (mM) : maximum concentration of neurotransmitter } ASSIGNED { v (mV) : postsynaptic voltage i (nA) : current = g*(v - Erev) g (uS) : conductance rb (/ms) : binding rbb (/ms) : Blocked binding RMgB (/ms) RMgU (/ms) T (mM) : neurotransmiter concentration in the cleft tRel (ms) : spiking time of the presynaptic cell synon : turns the synapse on or Off (0 = off) (1 = on) w : weight of synapse } STATE { : Channel states (all fractions) C0 : unbound C1 : single bound C2 : double bound D : desensitized O : open CB0 : Blocked unbound CB1 : Blocked single bound CB2 : Blocked double bound DB : Blocked desensitized OB : Blocked open } INITIAL { T = 0 synon = 0 tRel = 0 rates(v) C0 = 1 C1 = 0 C2 = 0 D = 0 O = 0 CB0 = 0 CB1 = 0 CB2 = 0 DB = 0 OB = 0 } BREAKPOINT { SOLVE kstates METHOD sparse g = w * gmax * O i = g * (v - Erev) } KINETIC kstates { release(t) rb = Rb * T rates(v) ~ C0 <-> C1 ((2 * rb),Ru) ~ C1 <-> C2 (rb,(2 * Ru)) ~ C2 <-> D (Rd,Rr) ~ C2 <-> O (Ro,Rc) ~ O <-> OB (RMgB,RMgU) ~ OB <-> CB2 ((3*Rc),Ro) ~ CB2 <-> DB (Rd,Rr) ~ CB2 <-> CB1 ((2 * Ru),rb) ~ CB1 <-> CB0 (Ru,(2 * rb)) CONSERVE C0+C1+C2+D+O+CB0+CB1+CB2+DB+OB = 1 } NET_RECEIVE(weight) { if (flag == 0) { tRel = t : resets the alpha function synon = 1 : turns the synapse on. : The alpha function does not require to turn off the synase w = weight } } PROCEDURE release(t(ms)) { T = T_max * (t - tRel) / tau * exp(1 - (t - tRel) / tau) * synon VERBATIM return 0; ENDVERBATIM } PROCEDURE rates(v(mV)) { RMgB = 610e-3 * exp(1 (/mV) * -v / 17) * (mg / 1 (mM)) * 1 (/ms) : Magnesium Blocking RMgU = 5400e-3 * exp(1 (/mV) * v / 47) * 1 (/ms) : Magnesium Unblocking } mod2c-8.2.2/test/validation/mod/SynNMDA10_2_2.mod000066400000000000000000000123501425457616700211560ustar00rootroot00000000000000TITLE detailed model of glutamate NMDA receptors COMMENT ----------------------------------------------------------------------------- This is special version of the model that resets itself after 590 ms from the start of simulation some of its rate constants are re-estimated by cure fitting --> CA1 pyramidal cells Binding rate constant is set to be similar to the NMDA16 model Kinetic model of NMDA receptors =============================== 10-state gating model: Vargas-Caballero & Robinson 2004, J Neurosci. 24(27):6171-6180 D DB | | C0 -- C1 -- C2 -- O -- OB -- CB2 -- CB1 -- CB0 Voltage dependence of Mg2+ block and slow voltage dependent unblok: Vargas-Caballero & Robinson, 2004, J. Neurosci. 24(27):6171-6180 ----------------------------------------------------------------------------- Based on voltage-clamp recordings of NMDA receptor-mediated currents in rat hippocampal slices (Vargas-Caballero & Robinson 2003 J Neurophysiol 89: 2778-2783), this model was fit directly to experimental recordings in order to obtain the optimal values for the parameters (see Vargas-Caballero & Robinson 2004, J. Neurosci. 24(27):6171-6180). ----------------------------------------------------------------------------- See details in: Destexhe, A., Mainen, Z.F. and Sejnowski, T.J. Kinetic models of synaptic transmission. In: Methods in Neuronal Modeling (2nd edition; edited by Koch, C. and Segev, I.), MIT press, Cambridge, 1998, pp 1-25. (electronic copy available at http://cns.iaf.cnrs-gif.fr) Written by Alain Destexhe and Zach Mainen, 1995 ----------------------------------------------------------------------------- These modifications are made by Keivan Moradi 2007 & 2012: - Release process modeled with an internal alpha function in order to make it compatible with NetCon onbject, and therefore does not require an external release mechanism. - Unit of g changed from pS to uS to make the synaptic weights compatible with NEURON's internal methods of modeling synapses (e.x. exp2syn) - gmax is set to 50 Johnson & Ascher, 1990 - Rate constants are corrected to be like the original article ----------------------------------------------------------------------------- ENDCOMMENT INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)} NEURON { POINT_PROCESS NMDA10_2_2 RANGE C0, C1, C2, D, O, CB0, CB1, CB2, DB, OB RANGE g, gmax, rb, RMgB, RMgU, Rd, Rr, Ro, Rc, Rb, Ru RANGE T_max, T, tau, tRel, Erev, synon GLOBAL mg NONSPECIFIC_CURRENT i } UNITS { (nA) = (nanoamp) (mV) = (millivolt) (pS) = (picosiemens) (uS) = (microsiemens) (umho) = (micromho) (mM) = (milli/liter) (uM) = (micro/liter) } PARAMETER { Erev = -0.7 (mV) : reversal potential gmax = 50 (pS) : maximal conductance mg = 1 (mM) : external magnesium concentration : Rates Rb = 2.83 (/mM /ms) : binding Ru = 38.1e-3 (/ms) : unbinding Rd = 4.7161 (/ms) : desensitization Rr = 0.16116 (/ms) : resensitization Ro = 0.099631 (/ms) : opening Rc = 0.056999 (/ms) : closing : alpha function formalism tau = .3 (ms) <1e-9,1e9> T_max = 1.5 (mM) : maximum concentration of neurotransmitter } ASSIGNED { v (mV) : postsynaptic voltage i (nA) : current = g*(v - Erev) g (uS) : conductance rb (/ms) : binding RMgB (/ms) RMgU (/ms) T (mM) : neurotransmiter concentration in the cleft tRel (ms) : spiking time of the presynaptic cell synon : turns the synapse on or Off (0 = off) (1 = on) w : weight of synapse } STATE { : Channel states (all fractions) C0 : unbound C1 : single bound C2 : double bound D : desensitized O : open CB0 : Blocked unbound CB1 : Blocked single bound CB2 : Blocked double bound DB : Blocked desensitized OB : Blocked open } INITIAL { T = 0 synon = 0 tRel = 0 rates(v) C0 = 1 C1 = 0 C2 = 0 D = 0 O = 0 CB0 = 0 CB1 = 0 CB2 = 0 DB = 0 OB = 0 net_send(590, 1) } BREAKPOINT { SOLVE kstates METHOD sparse g = w * gmax * O i = g * (v - Erev) } KINETIC kstates { release(t) rb = Rb * T rates(v) ~ C0 <-> C1 ((2 * rb),Ru) ~ C1 <-> C2 (rb,(2 * Ru)) ~ C2 <-> D (Rd,Rr) ~ C2 <-> O (Ro,Rc) ~ O <-> OB (RMgB,RMgU) ~ OB <-> CB2 ((3*Rc),Ro) ~ CB2 <-> DB (Rd,Rr) ~ CB2 <-> CB1 ((2 * Ru),rb) ~ CB1 <-> CB0 (Ru,(2 * rb)) CONSERVE C0+C1+C2+D+O+CB0+CB1+CB2+DB+OB = 1 } NET_RECEIVE(weight) { if (flag == 0) { tRel = t : resets the alpha function synon = 1 : turns the synapse on. : The alpha function does not require to turn off the synase w = weight } if (flag == 1) { : this reseting part is temporarily used to fit both recordings at the same time C0 = 1 C1 = 0 C2 = 0 D = 0 O = 0 CB0 = 0 CB1 = 0 CB2 = 0 DB = 0 OB = 0 } } PROCEDURE release(t(ms)) { T = T_max * (t - tRel) / tau * exp(1 - (t - tRel) / tau) * synon : VERBATIM : return 0; : ENDVERBATIM } PROCEDURE rates(v(mV)) { RMgB = 610e-3 * exp(1 (/mV) * -v / 17) * (mg / 1 (mM)) * 1 (/ms) : Magnesium Blocking RMgU = 5400e-3 * exp(1 (/mV) * v / 47) * 1 (/ms) : Magnesium Unblocking }mod2c-8.2.2/test/validation/mod/SynNMDA16.mod000066400000000000000000000141511425457616700205230ustar00rootroot00000000000000TITLE Voltage-dependent kinetic model of NMDA receptor COMMENT ----------------------------------------------------------------------------- Kinetic model of NMDA receptors =============================== 16-state gating model: Clarke and Johnson, 2008 RA2d1 RA2d1Mg | - RA2f - - RA2fMg - | R -- RA -- RA2 =< >= RA2O -- RA2OMg =< >= RA2Mg -- RAMg -- RMg | - RA2s - - RA2sMg - | RA2d2 RA2d2Mg ----------------------------------------------------------------------------- Based on voltage-clamp recordings of NMDA receptor-mediated currents in nucleated patches of rat layer II/III cortical pyramidal cells in the occipital cortex (Clarke and Johnson, 2008), this model was originally fitted with Matlab to experimental recordings in order to obtain the optimal values for the parameters. ----------------------------------------------------------------------------- Release process modeled with an internal alpha function in order to make it compatible with NetCon onbject, and therefore does not require an external release mechanism. ----------------------------------------------------------------------------- Unit of g is in uS to make the synaptic weights compatible with NEURON's internal methods of modeling synapses (e.x. exp2syn) for more information see the chapter 10 of the neuron book This mod file is written by Keivan Moradi 2012 ----------------------------------------------------------------------------- ENDCOMMENT INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)} NEURON { POINT_PROCESS NMDA16 USEION na READ nao RANGE T_max, T, tau, tRel, Erev, synon RANGE R,RA,RA2,RA2d1,RA2d2,RA2f,RA2s,O,OMg,RMg,RAMg,RA2Mg,RA2d1Mg,RA2d2Mg,RA2fMg,RA2sMg RANGE g, kd1F, kd1B, kd2F, kd2B, csi GLOBAL Kcs, kP, kNo, kNi, kMgF, kMgB, ksF, ksB, kfF, kfB NONSPECIFIC_CURRENT i THREADSAFE } UNITS { (nA) = (nanoamp) (mV) = (millivolt) (pS) = (picosiemens) (uS) = (microsiemens) (umho) = (micromho) (mM) = (milli/liter) (uM) = (micro/liter) } PARAMETER { Erev = 0 (mV) : reversal potential gmax = 50 (pS) : maximal conductance Johnson & Ascher, 1990 Mg = 1 (mM) : external magnesium concentration : alpha function formalism tau = .3 (ms) <1e-9,1e9> T_max = 1.5 (mM) : maximum concentration of neurotransmitter : Rates kon = 2.83 (/ms /mM) koff = 38.1e-3 (/ms) : voltage dependent rates ksF0 = 48e-3 (/ms) ksB0 = 230e-3 (/ms) kfF0 = 2836e-3 (/ms) kfB0 = 175e-3 (/ms) Vdep = 175 (mV) : sensitivity to membrane voltage V0 = -100 (mV) : the membrane voltage with no voltage-dependetn component : kd1F, kd1B, kd2F and kd2B should be found with optimization method since : NMDAR in different regions of the brain have different time course kd1F = 1e-3 (/ms) kd1B = 1e-3 (/ms) kd2F = 1e-3 (/ms) kd2B = 1e-3 (/ms) : Parameters that control the Mg block as in Antonov99 Kna = 34.4 (mM) Kcs0 = 0.27 (mM) a = -21 (mV) kP0 = 1.10e3 (/ms /mM) b = -55 (mV) kNo0 = 1.10e2 (/ms) c = 52.7 (mV) kNi0 = 61.8e-3 (/ms) d = -50 (mV) csi = 148 (mM) : internal Cs++ concentration (125 mM CsCl + 23 mM CsOH) : KMg0 = 101e-3 (mM) : e = 26.9 (mV) } ASSIGNED { v (mV) : postsynaptic voltage i (nA) : current = g*(v - Erev) g (uS) : conductance T (mM) : neurotransmiter concentration in the cleft tRel (ms) : spiking time of the presynaptic cell synon : turns the synapse on or Off w : weight of synapse : voltage-dependnent rates ksF (/ms) ksB (/ms) kfF (/ms) kfB (/ms) : Mg-block and -unblock rates kMgF (/ms /mM) kMgB (/ms) : Parameters that Mg-block and -unblock rates or the so called apparent-block and -unblock Kcs (mM) kP (/ms /mM) kNo (/ms) kNi (/ms) nao (mM) : Na+ concentration outside the cell, its value should be assigned in the hoc section : KMg (mM) } STATE { : Channel states (all fractions) R RA RA2 RA2d1 RA2d2 RA2f RA2s O OMg RMg RAMg RA2Mg RA2d1Mg RA2d2Mg RA2fMg RA2sMg } INITIAL { T = 0 synon = 0 tRel = 0 R = 1 rates(v,t) } BREAKPOINT { SOLVE kstates METHOD sparse g = w * gmax * O i = g * (v - Erev) } KINETIC kstates { rates(v,t) : RA2d1 RA2d1Mg : | - RA2f - - RA2fMg - | : R -- RA -- RA2 =< >= O -- OMg =< >= RA2Mg -- RAMg -- RMg : | - RA2s - - RA2sMg - | : RA2d2 RA2d2Mg ~ R <-> RA ((2*kon*T),koff) ~ RA <-> RA2 ((kon*T),(2*koff)) ~ RA2 <-> RA2d1 (kd1F,kd1B) ~ RA2 <-> RA2d2 (kd2F,kd2B) ~ RA2 <-> RA2f (kfF,kfB) ~ RA2 <-> RA2s (ksF,ksB) ~ RA2f <-> O (ksF,ksB) ~ RA2s <-> O (kfF,kfB) ~ O <-> OMg ((kMgF*Mg),kMgB) ~ OMg <-> RA2fMg (ksB,ksF) ~ OMg <-> RA2sMg (kfB,kfF) ~ RA2fMg <-> RA2Mg (kfB,kfF) ~ RA2sMg <-> RA2Mg (ksB,ksF) ~ RA2Mg <-> RA2d1Mg (kd1B,kd1F) ~ RA2Mg <-> RA2d2Mg (kd2B,kd2F) ~ RA2Mg <-> RAMg ((2*koff),(kon*T)) ~ RAMg <-> RMg (koff,(2*kon*T)) CONSERVE R+RA+RA2+RA2d1+RA2d2+RA2f+RA2s+O+OMg+RMg+RAMg+RA2Mg+RA2d1Mg+RA2d2Mg+RA2fMg+RA2sMg = 1 } NET_RECEIVE(weight) { if (flag == 0) { tRel = t : resets the alpha function synon = 1 : turns the synapse on. : The alpha function does not require to turn off the synase w = weight } } PROCEDURE rates(v (mV), t(ms)) { T = T_max * (t - tRel) / tau * exp(1 - (t - tRel) / tau) * synon Kcs = Kcs0 * exp(v/a) kP = kP0 * exp(v/b) kNo = kNo0 * exp(v/c) kNi = kNi0 * exp(v/d) kMgF = kP / ((1 + nao/Kna) * (1 + nao/Kna + csi/Kcs)) kMgB = kNo / (1 + nao/Kna)^2 + kNi : KMg = KMg0 * exp(v/e) ksF = ksF0 * exp((v - V0) / Vdep) ksB = ksB0 * exp((v - V0) / Vdep * (-1)) kfF = kfF0 * exp((v - V0) / Vdep) kfB = kfB0 * exp((v - V0) / Vdep * (-1)) } mod2c-8.2.2/test/validation/mod/SynNMDA16_2.mod000066400000000000000000000157151425457616700207530ustar00rootroot00000000000000TITLE Voltage-dependent kinetic model of NMDA receptor COMMENT This is an especial version of our model in which model would reset itself after 590 ms from the start of simulation some of its rate constants are re-estimated by cure fitting --> CA1 pyramidal cells Mg-block rate is similar to the NMDA10_2 model because we do not want to model a Cs++ containing internal solution ----------------------------------------------------------------------------- Kinetic model of NMDA receptors =============================== 16-state gating model: Clarke and Johnson, 2008 RA2d1 RA2d1Mg | - RA2f - - RA2fMg - | R -- RA -- RA2 =< >= RA2O -- RA2OMg =< >= RA2Mg -- RAMg -- RMg | - RA2s - - RA2sMg - | RA2d2 RA2d2Mg ----------------------------------------------------------------------------- Based on voltage-clamp recordings of NMDA receptor-mediated currents in nucleated patches of rat layer II/III cortical pyramidal cells in the occipital cortex (Clarke and Johnson, 2008), this model was originally fitted with Matlab to experimental recordings in order to obtain the optimal values for the parameters. ----------------------------------------------------------------------------- Release process modeled with an internal alpha function in order to make it compatible with NetCon onbject, and therefore does not require an external release mechanism. ----------------------------------------------------------------------------- Unit of g is in uS to make the synaptic weights compatible with NEURON's internal methods of modeling synapses (e.x. exp2syn) for more information see the chapter 10 of the neuron book This mod file is written by Keivan Moradi 2012 ----------------------------------------------------------------------------- ENDCOMMENT INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)} NEURON { POINT_PROCESS NMDA16_2 USEION na READ nao RANGE T_max, T, tau, tRel, Erev, synon RANGE R,RA,RA2,RA2d1,RA2d2,RA2f,RA2s,O,OMg,RMg,RAMg,RA2Mg,RA2d1Mg,RA2d2Mg,RA2fMg,RA2sMg RANGE g, kd1F, kd1B, kd2F, kd2B, csi GLOBAL Kcs, kP, kNo, kNi, kMgF, kMgB, ksF, ksB, kfF, kfB NONSPECIFIC_CURRENT i THREADSAFE } UNITS { (nA) = (nanoamp) (mV) = (millivolt) (pS) = (picosiemens) (uS) = (microsiemens) (umho) = (micromho) (mM) = (milli/liter) (uM) = (micro/liter) } PARAMETER { Erev = -0.7 (mV) : reversal potential gmax = 50 (pS) : maximal conductance Johnson & Ascher, 1990 Mg = 1 (mM) : external magnesium concentration : alpha function formalism tau = .3 (ms) <1e-9,1e9> T_max = 1.5 (mM) : maximum concentration of neurotransmitter : Rates kon = 2.83 (/ms /mM) koff = 38.1e-3 (/ms) : voltage dependent rates ksF0 = 48e-3 (/ms) ksB0 = 230e-3 (/ms) kfF0 = 2836e-3 (/ms) kfB0 = 175e-3 (/ms) : Vdep = 175 (mV) : sensitivity to membrane voltage V0 = -100 (mV) : the membrane voltage with no voltage-dependetn component : kd1F, kd1B, kd2F and kd2B should be found with optimization method since : NMDAR in different regions of the brain have different time course kd1F = 0.55 (/ms) kd1B = 0.081 (/ms) kd2F = 0.32319 (/ms) kd2B = 0.00020977 (/ms) : Parameters that control the Mg block as in Antonov99 Kna = 34.4 (mM) Kcs0 = 0.27 (mM) a = -21 (mV) kP0 = 1.10e3 (/ms /mM) b = -55 (mV) kNo0 = 1.10e2 (/ms) c = 52.7 (mV) kNi0 = 61.8e-3 (/ms) d = -50 (mV) csi = 148 (mM) : internal Cs++ concentration (125 mM CsCl + 23 mM CsOH) } ASSIGNED { v (mV) : postsynaptic voltage i (nA) : current = g*(v - Erev) g (uS) : conductance T (mM) : neurotransmiter concentration in the cleft tRel (ms) : spiking time of the presynaptic cell synon : turns the synapse on or Off w : weight of synapse : voltage-dependnent rates ksF (/ms) ksB (/ms) kfF (/ms) kfB (/ms) : Mg-block and -unblock rates kMgF (/ms /mM) kMgB (/ms) : Parameters that Mg-block and -unblock rates or the so called apparent-block and -unblock Kcs (mM) kP (/ms /mM) kNo (/ms) kNi (/ms) nao (mM) : Na+ concentration outside the cell, its value should be assigned in the hoc section } STATE { : Channel states (all fractions) R RA RA2 RA2d1 RA2d2 RA2f RA2s O OMg RMg RAMg RA2Mg RA2d1Mg RA2d2Mg RA2fMg RA2sMg } INITIAL { T = 0 synon = 0 tRel = 0 R = 1 rates(v,t) net_send(590, 1) } BREAKPOINT { SOLVE kstates METHOD sparse g = w * gmax * O i = g * (v - Erev) } KINETIC kstates { rates(v,t) : RA2d1 RA2d1Mg : | - RA2f - - RA2fMg - | : R -- RA -- RA2 =< >= O -- OMg =< >= RA2Mg -- RAMg -- RMg : | - RA2s - - RA2sMg - | : RA2d2 RA2d2Mg ~ R <-> RA ((2*kon*T),koff) ~ RA <-> RA2 ((kon*T),(2*koff)) ~ RA2 <-> RA2d1 (kd1F,kd1B) ~ RA2 <-> RA2d2 (kd2F,kd2B) ~ RA2 <-> RA2f (kfF,kfB) ~ RA2 <-> RA2s (ksF,ksB) ~ RA2f <-> O (ksF,ksB) ~ RA2s <-> O (kfF,kfB) ~ O <-> OMg ((kMgF*Mg),kMgB) ~ OMg <-> RA2fMg (ksB,ksF) ~ OMg <-> RA2sMg (kfB,kfF) ~ RA2fMg <-> RA2Mg (kfB,kfF) ~ RA2sMg <-> RA2Mg (ksB,ksF) ~ RA2Mg <-> RA2d1Mg (kd1B,kd1F) ~ RA2Mg <-> RA2d2Mg (kd2B,kd2F) ~ RA2Mg <-> RAMg ((2*koff),(kon*T)) ~ RAMg <-> RMg (koff,(2*kon*T)) CONSERVE R+RA+RA2+RA2d1+RA2d2+RA2f+RA2s+O+OMg+RMg+RAMg+RA2Mg+RA2d1Mg+RA2d2Mg+RA2fMg+RA2sMg = 1 } NET_RECEIVE(weight) { if (flag == 0) { tRel = t : resets the alpha function synon = 1 : turns the synapse on. : The alpha function does not require to turn off the synase w = weight } if (flag == 1) { : this reseting part is temporarily used to fit both recordings at the same time R = 1 RA = 0 RA2 = 0 RA2d1 = 0 RA2d2 = 0 RA2f = 0 RA2s = 0 O = 0 OMg = 0 RMg = 0 RAMg = 0 RA2Mg = 0 RA2d1Mg = 0 RA2d2Mg = 0 RA2fMg = 0 RA2sMg = 0 } } PROCEDURE rates(v (mV), t(ms)) { T = T_max * (t - tRel) / tau * exp(1 - (t - tRel) / tau) * synon : Mg block mechanism similar to Clarke & Johnson, 2008 : Kcs = Kcs0 * exp(v/a) : kP = kP0 * exp(v/b) : kNo = kNo0 * exp(v/c) : kNi = kNi0 * exp(v/d) : kMgF = kP / ((1 + nao/Kna) * (1 + nao/Kna + csi/Kcs)) : kMgB = kNo / (1 + nao/Kna)^2 + kNi : Mg block mechanism similar to Vargas-Caballero & Robinson, 2004 kMgF = 610e-3 * exp(1 (/mV) * -v / 17) * 1 (/mM /ms) : Magnesium Blocking kMgB = 5400e-3 * exp(1 (/mV) * v / 47) * 1 (/ms) : Magnesium Unblocking ksF = ksF0 * exp((v - V0) / Vdep) ksB = ksB0 * exp((v - V0) / Vdep * (-1)) kfF = kfF0 * exp((v - V0) / Vdep) kfB = kfB0 * exp((v - V0) / Vdep * (-1)) } mod2c-8.2.2/test/validation/mod/is.mod000066400000000000000000000026131425457616700175560ustar00rootroot00000000000000TITLE Cardiac L-type Calcium channel : from BEELER & REUTER, J.Physiol, 1977 NEURON { THREADSAFE SUFFIX Is USEION ca READ cai WRITE ica USEION cs WRITE ics VALENCE 2 USEION ns WRITE ins VALENCE 2 RANGE gsbar, ica, ics GLOBAL minf, ninf, mtau, ntau } UNITS { (mA) = (milliamp) (mV) = (millivolt) (mM) = (milli/liter) (S) = (siemens) } PARAMETER { gsbar= 5e-05(S/cm2) <0,1e9> } STATE { : d f m n } ASSIGNED { v (mV) celsius (degC) : 37 cai (mM) ica (mA/cm2) ics (mA/cm2) ins (mA/cm2) minf ninf mtau (ms) ntau (ms) lca } INITIAL { rates(v) m = minf n = ninf } BREAKPOINT { LOCAL Es SOLVE states METHOD derivimplicit Es = -82.3-13.0287*log(cai) ics = gsbar*m*n*(v - Es) ica = ics ins = -ics } DERIVATIVE states { rates(v) m' = (minf - m)/mtau n' = (ninf - n)/ntau } UNITSOFF FUNCTION alp(v(mV),i) (ms) { if (i==0) { alp = 0.095*exp(-0.01*(v - 5))/(exp(-0.072*(v - 5))+1) }else if (i==1){ alp = 0.012*exp(-0.008*(v + 28))/(exp(0.15*(v + 28))+1) } } FUNCTION bet(v(mV),i) { if (i==0) { bet = 0.07*exp(-0.017*(v + 44))/(exp(0.05*(v + 44))+1) }else if (i==1){ bet = 0.0065*exp(-0.02*(v + 30))/(exp(-0.2*(v + 30))+1) } } UNITSON PROCEDURE rates(v(mV)) { LOCAL a, b :TABLE minf, ninf, mtau, ntau DEPEND celsius FROM -100 TO 100 WITH 200 a = alp(v,0) b=bet(v,0) mtau = 1/(a + b) minf = a/(a + b) a = alp(v,1) b=bet(v,1) ntau = 1/(a + b) ninf = a/(a + b) }mod2c-8.2.2/test/validation/mod/isi.mod000066400000000000000000000046751425457616700177410ustar00rootroot00000000000000TITLE Cardiac second inward current COMMENT modified From DiFrancesco & Noble 1985 Phil Trans R Soc Lond 307:353-398 modified for Neuron by FE GANNIER francois.gannier@univ-tours.fr (University of TOURS) ENDCOMMENT INCLUDE "Unit.inc" INCLUDE "Volume.inc" NEURON { SUFFIX Isi USEION ca READ cao, cai WRITE ica USEION k READ ko, ki WRITE ik USEION na READ nao, nai WRITE ina RANGE P, ica, ik, ina, isi GLOBAL minf, mtau, hinf, htau } PARAMETER { P = 15 (nA/mM) alpha_f2 = 5 (/s) Kmf2 = 0.001 (mM) } STATE { : d, f, f2 m n h } ASSIGNED { v (mV) celsius (degC) : 37 isi (mA/cm2) ica (mA/cm2) ik (mA/cm2) ina (mA/cm2) eca (mV) minf ninf hinf mtau (ms) ntau (ms) htau (ms) cai (mM) cao (mM) nai (mM) nao (mM) ki (mM) ko (mM) beta_f2 (/s) } LOCAL RT INITIAL { RT = (1000)*R*(273.15+celsius) rate(v) m = minf n = ninf h = hinf } BREAKPOINT { LOCAL com, com2, Eo, icat, inat, ikt SOLVE states METHOD derivimplicit Eo = v - 50 com = (1e-06)* P/S*Eo*F/RT * m*n*h icat = 4*com /(1 - exp(-2*Eo*F/RT))*(cai*exp(100(mV)*F/RT) - cao*exp(-2*F*Eo/RT)) ica = icat com2 = 0.01*com /(1 - exp(-Eo*F/RT)) ikt = com2*(ki*exp(50(mV)*F/RT) - ko*exp(-F*Eo/RT)) ik = ikt inat = com2*(nai*exp(50(mV)*F/RT) - nao*exp(-F*Eo/RT)) ina = inat isi = inat + ikt + icat } DERIVATIVE states { : d, f, f2 rate(v) m' = (minf - m)/mtau n' = (ninf - n)/ntau h' = (0.001)*(alpha_f2 - h * (alpha_f2 + beta_f2)) beta_f2 = cai * alpha_f2 / Kmf2 } FUNCTION alp(v(mV), i) (/ms) { : order d, f LOCAL Eo, E1 if (i==0) { Eo = v + 24 if (fabs(Eo*1(/mV)) < 1e-5) { alp = (0.001)*120 (/s) } else { alp = (0.001)*30(/s/mV)*Eo / (1 - exp(-Eo/4(mV))) } } else if (i==1) { E1 = v + 34 if (fabs(E1*1(/mV)) < 1e-5) { alp = (0.001)*25 (/s) } else { alp = (0.001)*6.25(/mV/s)*E1/(exp(E1/4(mV))-1) } } } FUNCTION bet(v(mV), i) (/ms) { : order d,f LOCAL Eo if (i==0) { Eo = v + 24 if (fabs(Eo*1(/mV)) < 1e-5) { bet = (0.001)*120 (/s) } else { bet = (0.001)*12(/mV/s) *Eo / (exp(Eo/10(mV)) -1) } } else if (i==1) { bet = (0.001)*50(/s)/(1 + exp(-(v + 34)/4(mV))) } } PROCEDURE rate(v (mV)) { LOCAL a,b : TABLE minf, mtau, ninf, ntau FROM -100 TO 100 WITH 200 a = alp(v,0) b = bet(v,0) mtau = 1/(a + b) minf = a * mtau a = alp(v,1) b = bet(v,1) ntau = 1/(a + b) ninf = a * ntau } mod2c-8.2.2/test/validation/mod/zoidsyn.mod000066400000000000000000000046371425457616700206520ustar00rootroot00000000000000COMMENT zoidsyn.mod Generates a train of symmetrically trapeZoidal conductance changes. User specifies trf (duration of rise/fall ramps), tp (duration of plateau), start (onset of first trapezoid), interval, i.e. period between trapezoid onsets), and number of trapezoids. Error checking in INIT block ensures that interval is longer than trapezoid duration. 4/1/2012 NTC, minor modifications 4/3/2012 TMM ENDCOMMENT NEURON { POINT_PROCESS ZoidSyn RANGE trf, tp RANGE start, interval, number RANGE e, gmax, g, i NONSPECIFIC_CURRENT i } UNITS { (mV) = (millivolt) (nS) = (nanosiemens) (nA) = (nanoamp) } PARAMETER { trf (ms) <0, 1e9> : duration of rising and falling phases tp (ms) <0, 1e9> : duration of plateau start (ms) <0, 1e9> : latency of first transient interval (ms) <0, 1e9> : period, i.e. interval between transient onsets number : how many to deliver e (mV) : reversal potential gmax (nS) <0, 1e9> : conductance during plateau } ASSIGNED { v (mV) i (nA) on tally : how many more to deliver m (1/ms) b (1) dur (ms) : sum of twice the rise/fall time trp plus tp t0 (ms) g (nS) } INITIAL { if (trf <= 0) { trf = 1 UNITSOFF printf("trf must be longer than 0\n") printf("trf has been increased to %g ms\n", trf) UNITSON } if (tp < 0) { tp = 0 UNITSOFF printf("tp must not be negative\n") printf("tp has been changed to %g ms\n", tp) UNITSON } dur = 2*trf + tp if (interval <= dur) { interval = dur + 1 (ms) UNITSOFF printf("interval must be longer than trapezoid duration\n") printf("interval has been increased to %g ms\n", interval) UNITSON } on = 0 m = 0 b = 0 tally = number if (tally > 0) { net_send(start, 1) tally = tally - 1 } } BREAKPOINT { g = gmax * (m*(t-t0) + b) i = (0.001)*g*(v-e) } NET_RECEIVE (w) { if ((on == 0) && (flag == 1)) { : enter rising phase t0 = t m = 1/trf b = 0 on = 1 : prepare for plateau phase net_send(trf, 2) } if (flag == 2) { : enter plateau m = 0 b = 1 : prepare for falling phase net_send(tp, 3) } if (flag == 3) { : enter falling phase t0 = t m = -1/trf b = 1 : prepare to end net_send(trf, 4) } if (flag == 4) { : end m = 0 b = 0 on = 0 if (tally > 0) { : prepare to turn it on again net_send(interval - dur, 1) tally = tally - 1 } } } mod2c-8.2.2/test/validation/mod2c_core/000077500000000000000000000000001425457616700176755ustar00rootroot00000000000000mod2c-8.2.2/test/validation/mod2c_core/cpp/000077500000000000000000000000001425457616700204575ustar00rootroot00000000000000mod2c-8.2.2/test/validation/mod2c_core/cpp/NaSm.cpp000066400000000000000000000370731425457616700220330ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _slist1[0:1], _dlist1[0:1] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__NaSm #define nrn_cur _nrn_cur__NaSm #define _nrn_current _nrn_current__NaSm #define nrn_jacob _nrn_jacob__NaSm #define nrn_state _nrn_state__NaSm #define initmodel initmodel__NaSm #define _net_receive _net_receive__NaSm #define _net_init _net_init__NaSm #define nrn_state_launcher nrn_state_NaSm_launcher #define nrn_cur_launcher nrn_cur_NaSm_launcher #define nrn_jacob_launcher nrn_jacob_NaSm_launcher #define rates rates_NaSm #define states states_NaSm #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gnasmbar _p[0*_STRIDE] #define minf _p[1*_STRIDE] #define mtau _p[2*_STRIDE] #define gnasm _p[3*_STRIDE] #define m _p[4*_STRIDE] #define Dm _p[5*_STRIDE] #define ina _p[6*_STRIDE] #define _v_unused _p[7*_STRIDE] #define _g_unused _p[8*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_ina _nt_data[_ppvar[0*_STRIDE]] #define _ion_dinadv _nt_data[_ppvar[1*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ extern double celsius; #define _celsius_ _celsius__NaSm double _celsius_; #pragma acc declare copyin(_celsius_) #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_rates(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_NaSm", _hoc_setdata, "rates_NaSm", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ #define Etemp Etemp_NaSm double Etemp = 21; #pragma acc declare copyin (Etemp) #define Vtm Vtm_NaSm double Vtm = -33.5; #pragma acc declare copyin (Vtm) #define Vsm Vsm_NaSm double Vsm = -16; #pragma acc declare copyin (Vsm) #define ena ena_NaSm double ena = 40; #pragma acc declare copyin (ena) #define ktm ktm_NaSm double ktm = 26.3; #pragma acc declare copyin (ktm) #define ksm ksm_NaSm double ksm = 9.4; #pragma acc declare copyin (ksm) #define tom tom_NaSm double tom = 637.8; #pragma acc declare copyin (tom) static void _acc_globals_update() { #pragma acc update device (Etemp) if(nrn_threads->compute_gpu) #pragma acc update device (Vtm) if(nrn_threads->compute_gpu) #pragma acc update device (Vsm) if(nrn_threads->compute_gpu) #pragma acc update device (ena) if(nrn_threads->compute_gpu) #pragma acc update device (ktm) if(nrn_threads->compute_gpu) #pragma acc update device (ksm) if(nrn_threads->compute_gpu) #pragma acc update device (tom) if(nrn_threads->compute_gpu) _celsius_ = celsius; #pragma acc update device(_celsius_) } #define celsius _celsius_ #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "ena_NaSm", "mV", "gnasmbar_NaSm", "mho/cm2", 0,0 }; #endif /*BBCORE*/ static double delta_t = 1; #pragma acc declare copyin(delta_t) static double m0 = 0; #pragma acc declare copyin(m0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "ena_NaSm", &ena_NaSm, "Etemp_NaSm", &Etemp_NaSm, "Vsm_NaSm", &Vsm_NaSm, "ksm_NaSm", &ksm_NaSm, "tom_NaSm", &tom_NaSm, "Vtm_NaSm", &Vtm_NaSm, "ktm_NaSm", &ktm_NaSm, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NaSm", "gnasmbar_NaSm", 0, "minf_NaSm", "mtau_NaSm", "gnasm_NaSm", 0, "m_NaSm", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gnasmbar = 0.00011; prop_ion = need_memb(_na_sym); _ppvar[0]._pval = &prop_ion->param[3]; /* ina */ _ppvar[1]._pval = &prop_ion->param[4]; /* _ion_dinadv */ #endif /* BBCORE */ } static void _initlists(); static void _update_ion_pointer(Datum*); #define _psize 9 #define _ppsize 2 void _NaSm_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 1); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "na_ion"); hoc_register_dparam_semantics(_mechtype, 1, "na_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "A slow Sodium current"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int rates(_threadargsprotocomma_ double); static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_NaSm int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NaSm int* _dlist1; #pragma acc declare create(_dlist1) static inline int states(_threadargsproto_); /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { rates ( _threadargscomma_ v ) ; Dm = ( minf - m ) / mtau ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { rates ( _threadargscomma_ v ) ; Dm = Dm / (1. - dt*( ( ( ( - 1.0 ) ) ) / mtau )) ; return 0; } /*END CVODE*/ static int states (_threadargsproto_) { { rates ( _threadargscomma_ v ) ; m = m + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / mtau)))*(- ( ( ( minf ) ) / mtau ) / ( ( ( ( - 1.0) ) ) / mtau ) - m) ; } return 0; } static int rates ( _threadargsprotocomma_ double _lv ) { double _lq10 , _ltadj ; _lq10 = 2.5 ; _ltadj = pow( _lq10 , ( ( celsius - Etemp ) / 10.0 ) ) ; minf = 1.0 / ( 1.0 + exp ( - ( _lv - Vsm ) / ksm ) ) ; mtau = tom / ( exp ( - ( _lv - Vtm ) / ktm ) + exp ( ( _lv - Vtm ) / ktm ) ) / _ltadj ; return 0; } #if 0 /*BBCORE*/ static void _hoc_rates(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = 1.; rates ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ m = m0; { rates ( _threadargscomma_ v ) ; m = minf ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { gnasm = gnasmbar * m ; ina = gnasm * ( v - ena ) ; } _current += ina; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V _g = _nrn_current(_threadargs_, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_threadargs_, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { { states(_threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*1); _dlist1 = (int*)malloc(sizeof(int)*1); _slist1[0] = &(m) - _p; _dlist1[0] = &(Dm) - _p; #pragma acc enter data copyin(_slist1[0:1]) #pragma acc enter data copyin(_dlist1[0:1]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/Nap.cpp000066400000000000000000000361661425457616700217150ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _slist1[0:1], _dlist1[0:1] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__nap #define nrn_cur _nrn_cur__nap #define _nrn_current _nrn_current__nap #define nrn_jacob _nrn_jacob__nap #define nrn_state _nrn_state__nap #define initmodel initmodel__nap #define _net_receive _net_receive__nap #define _net_init _net_init__nap #define nrn_state_launcher nrn_state_nap_launcher #define nrn_cur_launcher nrn_cur_nap_launcher #define nrn_jacob_launcher nrn_jacob_nap_launcher #define states states_nap #define trates trates_nap #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gbar _p[0*_STRIDE] #define timestauh _p[1*_STRIDE] #define timestaum _p[2*_STRIDE] #define shifttaum _p[3*_STRIDE] #define shifttauh _p[4*_STRIDE] #define thegna _p[5*_STRIDE] #define minf _p[6*_STRIDE] #define mtau _p[7*_STRIDE] #define m _p[8*_STRIDE] #define ena _p[9*_STRIDE] #define ina _p[10*_STRIDE] #define Dm _p[11*_STRIDE] #define _v_unused _p[12*_STRIDE] #define _g_unused _p[13*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_ena _nt_data[_ppvar[0*_STRIDE]] #define _ion_ina _nt_data[_ppvar[1*_STRIDE]] #define _ion_dinadv _nt_data[_ppvar[2*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ extern double celsius; #define _celsius_ _celsius__nap double _celsius_; #pragma acc declare copyin(_celsius_) #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_trates(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_nap", _hoc_setdata, "trates_nap", _hoc_trates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ #define eNa eNa_nap double eNa = 55; #pragma acc declare copyin (eNa) static void _acc_globals_update() { #pragma acc update device (eNa) if(nrn_threads->compute_gpu) _celsius_ = celsius; #pragma acc update device(_celsius_) } #define celsius _celsius_ #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "eNa_nap", "mV", "gbar_nap", "mho/cm2", "thegna_nap", "mho/cm2", "mtau_nap", "ms", 0,0 }; #endif /*BBCORE*/ static double delta_t = 0.01; #pragma acc declare copyin(delta_t) static double m0 = 0; #pragma acc declare copyin(m0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "eNa_nap", &eNa_nap, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "nap", "gbar_nap", "timestauh_nap", "timestaum_nap", "shifttaum_nap", "shifttauh_nap", 0, "thegna_nap", "minf_nap", "mtau_nap", 0, "m_nap", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gbar = 0.0052085; timestauh = 1; timestaum = 1; shifttaum = 1; shifttauh = 1; prop_ion = need_memb(_na_sym); nrn_promote(prop_ion, 0, 1); _ppvar[0]._pval = &prop_ion->param[0]; /* ena */ _ppvar[1]._pval = &prop_ion->param[3]; /* ina */ _ppvar[2]._pval = &prop_ion->param[4]; /* _ion_dinadv */ #endif /* BBCORE */ } static void _initlists(); static void _update_ion_pointer(Datum*); #define _psize 14 #define _ppsize 3 void _Nap_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 1); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "na_ion"); hoc_register_dparam_semantics(_mechtype, 1, "na_ion"); hoc_register_dparam_semantics(_mechtype, 2, "na_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "nap"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int trates(_threadargsprotocomma_ double); static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_nap int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_nap int* _dlist1; #pragma acc declare create(_dlist1) static inline int states(_threadargsproto_); /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { mtau = 1.0 ; minf = ( 1.0 / ( 1.0 + exp ( - ( v + 52.3 ) / 6.8 ) ) ) ; Dm = ( minf - m ) / mtau ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { mtau = 1.0 ; minf = ( 1.0 / ( 1.0 + exp ( - ( v + 52.3 ) / 6.8 ) ) ) ; Dm = Dm / (1. - dt*( ( ( ( - 1.0 ) ) ) / mtau )) ; return 0; } /*END CVODE*/ static int states (_threadargsproto_) { { mtau = 1.0 ; minf = ( 1.0 / ( 1.0 + exp ( - ( v + 52.3 ) / 6.8 ) ) ) ; m = m + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / mtau)))*(- ( ( ( minf ) ) / mtau ) / ( ( ( ( - 1.0) ) ) / mtau ) - m) ; } return 0; } static int trates ( _threadargsprotocomma_ double _lvm ) { return 0; } #if 0 /*BBCORE*/ static void _hoc_trates(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = 1.; trates ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ m = m0; { mtau = 1.0 ; minf = ( 1.0 / ( 1.0 + exp ( - ( v + 52.3 ) / 6.8 ) ) ) ; m = minf ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V ena = _ion_ena; initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { mtau = 1.0 ; minf = ( 1.0 / ( 1.0 + exp ( - ( v + 52.3 ) / 6.8 ) ) ) ; thegna = gbar * m ; ina = thegna * ( v - eNa ) ; } _current += ina; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V ena = _ion_ena; _g = _nrn_current(_threadargs_, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_threadargs_, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { ena = _ion_ena; { states(_threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*1); _dlist1 = (int*)malloc(sizeof(int)*1); _slist1[0] = &(m) - _p; _dlist1[0] = &(Dm) - _p; #pragma acc enter data copyin(_slist1[0:1]) #pragma acc enter data copyin(_dlist1[0:1]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/NapDA.cpp000066400000000000000000000477221425457616700221220ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:3] , _slist1[0:2], _dlist1[0:2] , _slist2[0:2] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__NapDA #define nrn_cur _nrn_cur__NapDA #define _nrn_current _nrn_current__NapDA #define nrn_jacob _nrn_jacob__NapDA #define nrn_state _nrn_state__NapDA #define initmodel initmodel__NapDA #define _net_receive _net_receive__NapDA #define _net_init _net_init__NapDA #define nrn_state_launcher nrn_state_NapDA_launcher #define nrn_cur_launcher nrn_cur_NapDA_launcher #define nrn_jacob_launcher nrn_jacob_NapDA_launcher #define states states_NapDA #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gNapbar _p[0*_STRIDE] #define ena _p[1*_STRIDE] #define gna _p[2*_STRIDE] #define m _p[3*_STRIDE] #define h _p[4*_STRIDE] #define ina _p[5*_STRIDE] #define Dm _p[6*_STRIDE] #define Dh _p[7*_STRIDE] #define _v_unused _p[8*_STRIDE] #define _g_unused _p[9*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_ina _nt_data[_ppvar[0*_STRIDE]] #define _ion_dinadv _nt_data[_ppvar[1*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_hbet(void); static void _hoc_half(void); static void _hoc_mbet(void); static void _hoc_malf(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_NapDA", _hoc_setdata, "hbet_NapDA", _hoc_hbet, "half_NapDA", _hoc_half, "mbet_NapDA", _hoc_mbet, "malf_NapDA", _hoc_malf, 0, 0 }; #endif /*BBCORE*/ #define hbet hbet_NapDA #define half half_NapDA #define mbet mbet_NapDA #define malf malf_NapDA #pragma acc routine seq inline double hbet( _threadargsprotocomma_ double ); #pragma acc routine seq inline double half( _threadargsprotocomma_ double ); #pragma acc routine seq inline double mbet( _threadargsprotocomma_ double ); #pragma acc routine seq inline double malf( _threadargsprotocomma_ double ); /* declare global and static user variables */ static void _acc_globals_update() { } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "gNapbar_NapDA", 0, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "gNapbar_NapDA", "mho/cm2", "ena_NapDA", "mV", "gna_NapDA", "mho/cm2", 0,0 }; #endif /*BBCORE*/ static double delta_t = 0.01; #pragma acc declare copyin(delta_t) static double h0 = 0; #pragma acc declare copyin(h0) static double m0 = 0; #pragma acc declare copyin(m0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NapDA", "gNapbar_NapDA", "ena_NapDA", 0, "gna_NapDA", 0, "m_NapDA", "h_NapDA", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gNapbar = 0.0022; ena = 55; prop_ion = need_memb(_na_sym); _ppvar[0]._pval = &prop_ion->param[3]; /* ina */ _ppvar[1]._pval = &prop_ion->param[4]; /* _ion_dinadv */ #endif /* BBCORE */ } static void _initlists(); static void _thread_mem_init(ThreadDatum*); static void _thread_cleanup(ThreadDatum*); static void _update_ion_pointer(Datum*); #define _psize 10 #define _ppsize 2 void _NapDA_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 4); _extcall_thread = (ThreadDatum*)ecalloc(3, sizeof(ThreadDatum)); _thread_mem_init(_extcall_thread); _nrn_thread_reg1(_mechtype, _thread_mem_init); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "na_ion"); hoc_register_dparam_semantics(_mechtype, 1, "na_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = ""; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} #define _deriv1_advance _thread[0]._i #define _dith1 1 #define _newtonspace1 _thread[2]._pvoid static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ /* _derivimplicit_ states _NapDA */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct _newton_states_NapDA { int operator()(_threadargsproto_) const; }; #define _slist2 _slist2_NapDA int* _slist2; #pragma acc declare create(_slist2) #define _slist1 _slist1_NapDA int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NapDA int* _dlist1; #pragma acc declare create(_dlist1) struct states_NapDA { int operator()(_threadargsproto_) const; }; /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { Dm = ( 1.0 - m ) * malf ( _threadargscomma_ v ) - m * mbet ( _threadargscomma_ v ) ; Dh = ( ( 1.0 - h ) * half ( _threadargscomma_ v ) - h * hbet ( _threadargscomma_ v ) ) / 2.0 ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { Dm = Dm / (1. - dt*( (( ( - 1.0 ) ))*(malf ( _threadargscomma_ v )) - (1.0)*(mbet ( _threadargscomma_ v )) )) ; Dh = Dh / (1. - dt*( ( ( (( ( - 1.0 ) ))*(half ( _threadargscomma_ v )) - (1.0)*(hbet ( _threadargscomma_ v )) ) ) / 2.0 )) ; return 0; } /*END CVODE*/ int states ::operator()(_threadargsproto_) const { int _reset=0; int error = 0; { double* _savstate1 = (double*)_thread[_dith1]._pval; double* _dlist2 = (double*)(_thread[_dith1]._pval) + (2*_cntml_padded); {int _id; for(_id=0; _id < 2; _id++) { _savstate1[_id*_STRIDE] = _p[_slist1[_id]*_STRIDE];}} _reset = nrn_newton_thread(static_cast(_newtonspace1), 2, _slist2, _newton_states_NapDA{}, _dlist2, _threadargs_); /*if(_reset) {abort_run(_reset);}*/ } return _reset; } int _newton_states_NapDA::operator()(_threadargsproto_) const { int _reset=0; { double* _savstate1 = (double*)_thread[_dith1]._pval; double* _dlist2 = (double*)(_thread[_dith1]._pval) + (2*_cntml_padded); int _counte = -1; { Dm = ( 1.0 - m ) * malf ( _threadargscomma_ v ) - m * mbet ( _threadargscomma_ v ) ; Dh = ( ( 1.0 - h ) * half ( _threadargscomma_ v ) - h * hbet ( _threadargscomma_ v ) ) / 2.0 ; {int _id; for(_id=0; _id < 2; _id++) { if (_deriv1_advance) { _dlist2[(++_counte)*_STRIDE] = _p[_dlist1[_id]*_STRIDE] - (_p[_slist1[_id]*_STRIDE] - _savstate1[_id*_STRIDE])/dt; }else{ _dlist2[(++_counte)*_STRIDE] = _p[_slist1[_id]*_STRIDE] - _savstate1[_id*_STRIDE];}}} } } return _reset;} double malf ( _threadargsprotocomma_ double _lv ) { double _lmalf; double _lva ; _lva = _lv + 12.0 ; if ( fabs ( _lva ) < 1e-04 ) { _lmalf = - 0.2816 * ( - 9.3 - _lva * 0.5 ) ; } else { _lmalf = - 0.2816 * _lva / ( - 1.0 + exp ( - _lva / 9.3 ) ) ; } return _lmalf; } #if 0 /*BBCORE*/ static void _hoc_malf(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = malf ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ double mbet ( _threadargsprotocomma_ double _lv ) { double _lmbet; double _lvb ; _lvb = _lv - 15.0 ; if ( fabs ( _lvb ) < 1e-04 ) { _lmbet = 0.2464 * ( 6.0 - _lvb * 0.5 ) ; } else { _lmbet = 0.2464 * _lvb / ( - 1.0 + exp ( _lvb / 6.0 ) ) ; } return _lmbet; } #if 0 /*BBCORE*/ static void _hoc_mbet(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = mbet ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ double half ( _threadargsprotocomma_ double _lv ) { double _lhalf; _lhalf = 2.8e-5 * ( exp ( - ( _lv + 42.8477 ) / 4.0248 ) ) ; return _lhalf; } #if 0 /*BBCORE*/ static void _hoc_half(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = half ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ double hbet ( _threadargsprotocomma_ double _lv ) { double _lhbet; _lhbet = 0.02 / ( 1.0 + exp ( - ( _lv - 413.9284 ) / 148.2589 ) ) ; return _lhbet; } #if 0 /*BBCORE*/ static void _hoc_hbet(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = hbet ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _thread_mem_init(ThreadDatum* _thread) { _thread[_dith1]._pval = NULL; } static void _thread_cleanup(ThreadDatum* _thread) { free( _thread[_dith1]._pval); nrn_destroy_newtonspace((NewtonSpace*) _newtonspace1); } static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ h = h0; m = m0; { m = malf ( _threadargscomma_ v ) / ( malf ( _threadargscomma_ v ) + mbet ( _threadargscomma_ v ) ) ; h = half ( _threadargscomma_ v ) / ( half ( _threadargscomma_ v ) + hbet ( _threadargscomma_ v ) ) ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _deriv1_advance = 0; #ifdef _OPENACC #pragma acc update device (_deriv1_advance) if (_nt->compute_gpu) #endif if (!_newtonspace1) { _newtonspace1 = nrn_cons_newtonspace(2, _cntml_padded); _thread[_dith1]._pval = makevector(2*2*_cntml_padded*sizeof(double)); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_ns = (void*)acc_deviceptr(_newtonspace1); double* _d_pd = (double*)acc_copyin(_thread[_dith1]._pval,2*2*_cntml_padded* sizeof(double)); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[2]._pvoid), &_d_ns, sizeof(void*)); acc_memcpy_to_device(&(_d_td[_dith1]._pval), &_d_pd, sizeof(double*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V initmodel(_threadargs_); } } _deriv1_advance = 1; #ifdef _OPENACC #pragma acc update device (_deriv1_advance) if (_nt->compute_gpu) #endif } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { gna = gNapbar * m * h ; ina = gna * ( v - ena ) ; } _current += ina; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V _g = _nrn_current(_threadargs_, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_threadargs_, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { { derivimplicit_thread(2, _slist1, _dlist1, states_NapDA{}, _threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*2); _dlist1 = (int*)malloc(sizeof(int)*2); _slist1[0] = &(m) - _p; _dlist1[0] = &(Dm) - _p; _slist1[1] = &(h) - _p; _dlist1[1] = &(Dh) - _p; #pragma acc enter data copyin(_slist1[0:2]) #pragma acc enter data copyin(_dlist1[0:2]) _slist2 = (int*)malloc(sizeof(int)*2); _slist2[0] = &(h) - _p; _slist2[1] = &(m) - _p; #pragma acc enter data copyin(_slist2[0:2]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/NapIn.cpp000066400000000000000000000365411425457616700222010ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _slist1[0:2], _dlist1[0:2] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__napIn #define nrn_cur _nrn_cur__napIn #define _nrn_current _nrn_current__napIn #define nrn_jacob _nrn_jacob__napIn #define nrn_state _nrn_state__napIn #define initmodel initmodel__napIn #define _net_receive _net_receive__napIn #define _net_init _net_init__napIn #define nrn_state_launcher nrn_state_napIn_launcher #define nrn_cur_launcher nrn_cur_napIn_launcher #define nrn_jacob_launcher nrn_jacob_napIn_launcher #define states states_napIn #define trates trates_napIn #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gbar _p[0*_STRIDE] #define htau _p[1*_STRIDE] #define thegna _p[2*_STRIDE] #define minf _p[3*_STRIDE] #define hinf _p[4*_STRIDE] #define mtau _p[5*_STRIDE] #define m _p[6*_STRIDE] #define h _p[7*_STRIDE] #define ena _p[8*_STRIDE] #define ina _p[9*_STRIDE] #define Dm _p[10*_STRIDE] #define Dh _p[11*_STRIDE] #define _v_unused _p[12*_STRIDE] #define _g_unused _p[13*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_ena _nt_data[_ppvar[0*_STRIDE]] #define _ion_ina _nt_data[_ppvar[1*_STRIDE]] #define _ion_dinadv _nt_data[_ppvar[2*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ extern double celsius; #define _celsius_ _celsius__napIn double _celsius_; #pragma acc declare copyin(_celsius_) #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_trates(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_napIn", _hoc_setdata, "trates_napIn", _hoc_trates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ #define eNa eNa_napIn double eNa = 55; #pragma acc declare copyin (eNa) static void _acc_globals_update() { #pragma acc update device (eNa) if(nrn_threads->compute_gpu) _celsius_ = celsius; #pragma acc update device(_celsius_) } #define celsius _celsius_ #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "eNa_napIn", "mV", "gbar_napIn", "mho/cm2", "htau_napIn", "ms", "thegna_napIn", "mho/cm2", "mtau_napIn", "ms", 0,0 }; #endif /*BBCORE*/ static double delta_t = 0.01; #pragma acc declare copyin(delta_t) static double h0 = 0; #pragma acc declare copyin(h0) static double m0 = 0; #pragma acc declare copyin(m0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "eNa_napIn", &eNa_napIn, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "napIn", "gbar_napIn", "htau_napIn", 0, "thegna_napIn", "minf_napIn", "hinf_napIn", "mtau_napIn", 0, "m_napIn", "h_napIn", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gbar = 0.0052085; htau = 15; prop_ion = need_memb(_na_sym); nrn_promote(prop_ion, 0, 1); _ppvar[0]._pval = &prop_ion->param[0]; /* ena */ _ppvar[1]._pval = &prop_ion->param[3]; /* ina */ _ppvar[2]._pval = &prop_ion->param[4]; /* _ion_dinadv */ #endif /* BBCORE */ } static void _initlists(); static void _update_ion_pointer(Datum*); #define _psize 14 #define _ppsize 3 void _NapIn_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 1); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "na_ion"); hoc_register_dparam_semantics(_mechtype, 1, "na_ion"); hoc_register_dparam_semantics(_mechtype, 2, "na_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "nap"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int trates(_threadargsprotocomma_ double); static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_napIn int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_napIn int* _dlist1; #pragma acc declare create(_dlist1) static inline int states(_threadargsproto_); /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { trates ( _threadargscomma_ v ) ; Dm = ( minf - m ) / mtau ; Dh = ( hinf - h ) / htau ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { trates ( _threadargscomma_ v ) ; Dm = Dm / (1. - dt*( ( ( ( - 1.0 ) ) ) / mtau )) ; Dh = Dh / (1. - dt*( ( ( ( - 1.0 ) ) ) / htau )) ; return 0; } /*END CVODE*/ static int states (_threadargsproto_) { { trates ( _threadargscomma_ v ) ; m = m + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / mtau)))*(- ( ( ( minf ) ) / mtau ) / ( ( ( ( - 1.0) ) ) / mtau ) - m) ; h = h + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / htau)))*(- ( ( ( hinf ) ) / htau ) / ( ( ( ( - 1.0) ) ) / htau ) - h) ; } return 0; } static int trates ( _threadargsprotocomma_ double _lvm ) { mtau = 1.0 ; minf = 1.0 / ( 1.0 + exp ( - ( v + 52.3 ) / 6.8 ) ) ; hinf = 1.0 / ( 1.0 + exp ( ( v + 48.0 ) / 10.0 ) ) ; return 0; } #if 0 /*BBCORE*/ static void _hoc_trates(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = 1.; trates ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ h = h0; m = m0; { trates ( _threadargscomma_ v ) ; m = minf ; h = hinf ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V ena = _ion_ena; initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { trates ( _threadargscomma_ v ) ; thegna = gbar * m * h ; ina = thegna * ( v - eNa ) ; } _current += ina; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V ena = _ion_ena; _g = _nrn_current(_threadargs_, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_threadargs_, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { ena = _ion_ena; { states(_threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*2); _dlist1 = (int*)malloc(sizeof(int)*2); _slist1[0] = &(m) - _p; _dlist1[0] = &(Dm) - _p; _slist1[1] = &(h) - _p; _dlist1[1] = &(Dh) - _p; #pragma acc enter data copyin(_slist1[0:2]) #pragma acc enter data copyin(_dlist1[0:2]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/Nap_E.cpp000066400000000000000000000413421425457616700221510ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _slist1[0:2], _dlist1[0:2] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__Nap_E #define nrn_cur _nrn_cur__Nap_E #define _nrn_current _nrn_current__Nap_E #define nrn_jacob _nrn_jacob__Nap_E #define nrn_state _nrn_state__Nap_E #define initmodel initmodel__Nap_E #define _net_receive _net_receive__Nap_E #define _net_init _net_init__Nap_E #define nrn_state_launcher nrn_state_Nap_E_launcher #define nrn_cur_launcher nrn_cur_Nap_E_launcher #define nrn_jacob_launcher nrn_jacob_Nap_E_launcher #define rates rates_Nap_E #define states states_Nap_E #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gNap_Ebar _p[0*_STRIDE] #define ina _p[1*_STRIDE] #define gNap_E _p[2*_STRIDE] #define m _p[3*_STRIDE] #define h _p[4*_STRIDE] #define ttxo _p[5*_STRIDE] #define ttxi _p[6*_STRIDE] #define ena _p[7*_STRIDE] #define mInf _p[8*_STRIDE] #define mTau _p[9*_STRIDE] #define mAlpha _p[10*_STRIDE] #define mBeta _p[11*_STRIDE] #define hInf _p[12*_STRIDE] #define hTau _p[13*_STRIDE] #define hAlpha _p[14*_STRIDE] #define hBeta _p[15*_STRIDE] #define Dm _p[16*_STRIDE] #define Dh _p[17*_STRIDE] #define _v_unused _p[18*_STRIDE] #define _g_unused _p[19*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_ena _nt_data[_ppvar[0*_STRIDE]] #define _ion_ina _nt_data[_ppvar[1*_STRIDE]] #define _ion_dinadv _nt_data[_ppvar[2*_STRIDE]] #define _ion_ttxo _nt_data[_ppvar[3*_STRIDE]] #define _ion_ttxi _nt_data[_ppvar[4*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_rates(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_Nap_E", _hoc_setdata, "rates_Nap_E", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ static void _acc_globals_update() { } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "gNap_Ebar_Nap_E", "S/cm2", "ina_Nap_E", "mA/cm2", "gNap_E_Nap_E", "S/cm2", 0,0 }; #endif /*BBCORE*/ static double delta_t = 0.01; #pragma acc declare copyin(delta_t) static double h0 = 0; #pragma acc declare copyin(h0) static double m0 = 0; #pragma acc declare copyin(m0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "Nap_E", "gNap_Ebar_Nap_E", 0, "ina_Nap_E", "gNap_E_Nap_E", 0, "m_Nap_E", "h_Nap_E", 0, 0}; static int _na_type; static int _ttx_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gNap_Ebar = 1e-05; prop_ion = need_memb(_na_sym); nrn_promote(prop_ion, 0, 1); _ppvar[0]._pval = &prop_ion->param[0]; /* ena */ _ppvar[1]._pval = &prop_ion->param[3]; /* ina */ _ppvar[2]._pval = &prop_ion->param[4]; /* _ion_dinadv */ prop_ion = need_memb(_ttx_sym); nrn_promote(prop_ion, 1, 0); _ppvar[3]._pval = &prop_ion->param[2]; /* ttxo */ _ppvar[4]._pval = &prop_ion->param[1]; /* ttxi */ #endif /* BBCORE */ } static void _initlists(); static void _update_ion_pointer(Datum*); #define _psize 20 #define _ppsize 5 void _Nap_E_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); _ttx_type = nrn_get_mechtype("ttx_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); ion_reg("ttx", 1.0); _na_sym = hoc_lookup("na_ion"); _ttx_sym = hoc_lookup("ttx_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 1); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "na_ion"); hoc_register_dparam_semantics(_mechtype, 1, "na_ion"); hoc_register_dparam_semantics(_mechtype, 2, "na_ion"); hoc_register_dparam_semantics(_mechtype, 3, "ttx_ion"); hoc_register_dparam_semantics(_mechtype, 4, "ttx_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = ""; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int rates(_threadargsproto_); static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_Nap_E int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_Nap_E int* _dlist1; #pragma acc declare create(_dlist1) static inline int states(_threadargsproto_); /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { if ( ttxi == 0.015625 && ttxo > 1e-12 ) { mInf = 0.0 ; mTau = 1e-12 ; hInf = 1.0 ; hTau = 1e-12 ; } else { rates ( _threadargs_ ) ; } Dm = ( mInf - m ) / mTau ; Dh = ( hInf - h ) / hTau ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { if ( ttxi == 0.015625 && ttxo > 1e-12 ) { mInf = 0.0 ; mTau = 1e-12 ; hInf = 1.0 ; hTau = 1e-12 ; } else { rates ( _threadargs_ ) ; } Dm = Dm / (1. - dt*( ( ( ( - 1.0 ) ) ) / mTau )) ; Dh = Dh / (1. - dt*( ( ( ( - 1.0 ) ) ) / hTau )) ; return 0; } /*END CVODE*/ static int states (_threadargsproto_) { { if ( ttxi == 0.015625 && ttxo > 1e-12 ) { mInf = 0.0 ; mTau = 1e-12 ; hInf = 1.0 ; hTau = 1e-12 ; } else { rates ( _threadargs_ ) ; } m = m + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / mTau)))*(- ( ( ( mInf ) ) / mTau ) / ( ( ( ( - 1.0) ) ) / mTau ) - m) ; h = h + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / hTau)))*(- ( ( ( hInf ) ) / hTau ) / ( ( ( ( - 1.0) ) ) / hTau ) - h) ; } return 0; } static int rates ( _threadargsproto_ ) { mInf = 1.0 / ( 1.0 + exp ( ( v - - 52.6 ) / - 4.6 ) ) ; if ( v == - 25.0 ) { v = v + 0.0001 ; } mAlpha = ( 0.182 * ( v - - 25.0 ) ) / ( 1.0 - ( exp ( - ( v - - 25.0 ) / 9.0 ) ) ) ; mBeta = ( 0.124 * ( - v - 25.0 ) ) / ( 1.0 - ( exp ( - ( - v - 25.0 ) / 9.0 ) ) ) ; mTau = 6.0 * 1.0 / ( mAlpha + mBeta ) ; if ( v == - 50.0 ) { v = v + 0.0001 ; } hAlpha = ( 0.00001 * ( v - - 50.0 ) ) / ( 1.0 - ( exp ( - ( v - - 50.0 ) / 13.0 ) ) ) ; if ( v == - 75.0 ) { v = v + 0.0001 ; } hBeta = ( 0.00001 * ( - v - 75.0 ) ) / ( 1.0 - ( exp ( - ( - v - 75.0 ) / 13.0 ) ) ) ; hInf = 1.0 / ( 1.0 + exp ( ( v - - 48.8 ) / 10.0 ) ) ; hTau = ( 1.0 / ( hAlpha + hBeta ) ) ; return 0; } #if 0 /*BBCORE*/ static void _hoc_rates(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = 1.; rates ( _threadargs_ ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ h = h0; m = m0; { if ( ttxi == 0.015625 && ttxo > 1e-12 ) { mInf = 0.0 ; mTau = 1e-12 ; hInf = 1.0 ; hTau = 1e-12 ; } else { rates ( _threadargs_ ) ; } m = mInf ; h = hInf ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V ena = _ion_ena; ttxo = _ion_ttxo; ttxi = _ion_ttxi; initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { gNap_E = gNap_Ebar * m * m * m * h ; ina = gNap_E * ( v - ena ) ; } _current += ina; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V ena = _ion_ena; ttxo = _ion_ttxo; ttxi = _ion_ttxi; _g = _nrn_current(_threadargs_, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_threadargs_, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { ena = _ion_ena; ttxo = _ion_ttxo; ttxi = _ion_ttxi; { states(_threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*2); _dlist1 = (int*)malloc(sizeof(int)*2); _slist1[0] = &(m) - _p; _dlist1[0] = &(Dm) - _p; _slist1[1] = &(h) - _p; _dlist1[1] = &(Dh) - _p; #pragma acc enter data copyin(_slist1[0:2]) #pragma acc enter data copyin(_dlist1[0:2]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/Nap_No.cpp000066400000000000000000000367261425457616700223530ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _slist1[0:1], _dlist1[0:1] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__Nap_No #define nrn_cur _nrn_cur__Nap_No #define _nrn_current _nrn_current__Nap_No #define nrn_jacob _nrn_jacob__Nap_No #define nrn_state _nrn_state__Nap_No #define initmodel initmodel__Nap_No #define _net_receive _net_receive__Nap_No #define _net_init _net_init__Nap_No #define nrn_state_launcher nrn_state_Nap_No_launcher #define nrn_cur_launcher nrn_cur_Nap_No_launcher #define nrn_jacob_launcher nrn_jacob_Nap_No_launcher #define rates rates_Nap_No #define states states_Nap_No #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gnamax _p[0*_STRIDE] #define gna _p[1*_STRIDE] #define pinf _p[2*_STRIDE] #define ptau _p[3*_STRIDE] #define p _p[4*_STRIDE] #define Dp _p[5*_STRIDE] #define ena _p[6*_STRIDE] #define ina _p[7*_STRIDE] #define _v_unused _p[8*_STRIDE] #define _g_unused _p[9*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_ena _nt_data[_ppvar[0*_STRIDE]] #define _ion_ina _nt_data[_ppvar[1*_STRIDE]] #define _ion_dinadv _nt_data[_ppvar[2*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_rates(void); static void _hoc_vtrap(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_Nap_No", _hoc_setdata, "rates_Nap_No", _hoc_rates, "vtrap_Nap_No", _hoc_vtrap, 0, 0 }; #endif /*BBCORE*/ #define vtrap vtrap_Nap_No #pragma acc routine seq inline double vtrap( _threadargsprotocomma_ double , double ); /* declare global and static user variables */ static void _acc_globals_update() { } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "gnamax_Nap_No", 0, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "gnamax_Nap_No", "S/cm2", "gna_Nap_No", "S/cm2", "ptau_Nap_No", "ms", 0,0 }; #endif /*BBCORE*/ static double delta_t = 0.01; #pragma acc declare copyin(delta_t) static double p0 = 0; #pragma acc declare copyin(p0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "Nap_No", "gnamax_Nap_No", 0, "gna_Nap_No", "pinf_Nap_No", "ptau_Nap_No", 0, "p_Nap_No", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gnamax = 0.01; prop_ion = need_memb(_na_sym); nrn_promote(prop_ion, 0, 1); _ppvar[0]._pval = &prop_ion->param[0]; /* ena */ _ppvar[1]._pval = &prop_ion->param[3]; /* ina */ _ppvar[2]._pval = &prop_ion->param[4]; /* _ion_dinadv */ #endif /* BBCORE */ } static void _initlists(); static void _update_ion_pointer(Datum*); #define _psize 10 #define _ppsize 3 void _Nap_No_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 1); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "na_ion"); hoc_register_dparam_semantics(_mechtype, 1, "na_ion"); hoc_register_dparam_semantics(_mechtype, 2, "na_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "Nap_No.mod persistent sodium current"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int rates(_threadargsprotocomma_ double); static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_Nap_No int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_Nap_No int* _dlist1; #pragma acc declare create(_dlist1) static inline int states(_threadargsproto_); /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { rates ( _threadargscomma_ v ) ; Dp = ( pinf - p ) / ptau ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { rates ( _threadargscomma_ v ) ; Dp = Dp / (1. - dt*( ( ( ( - 1.0 ) ) ) / ptau )) ; return 0; } /*END CVODE*/ static int states (_threadargsproto_) { { rates ( _threadargscomma_ v ) ; p = p + (1. - exp(dt*(( ( ( - 1.0 ) ) ) / ptau)))*(- ( ( ( pinf ) ) / ptau ) / ( ( ( ( - 1.0) ) ) / ptau ) - p) ; } return 0; } static int rates ( _threadargsprotocomma_ double _lv ) { double _lalpha , _lbeta , _lsum ; _lalpha = 0.0353 * vtrap ( _threadargscomma_ - 17.0 - _lv , 10.2 ) ; _lbeta = 0.000883 * vtrap ( _threadargscomma_ _lv + 24.0 , 10.0 ) ; _lsum = _lalpha + _lbeta ; ptau = 1.0 / _lsum ; pinf = _lalpha / _lsum ; return 0; } #if 0 /*BBCORE*/ static void _hoc_rates(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = 1.; rates ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ double vtrap ( _threadargsprotocomma_ double _lx , double _ly ) { double _lvtrap; if ( fabs ( _lx / _ly ) < 1e-6 ) { _lvtrap = _ly * ( 1.0 - _lx / _ly / 2.0 ) ; } else { _lvtrap = _lx / ( exp ( _lx / _ly ) - 1.0 ) ; } return _lvtrap; } #if 0 /*BBCORE*/ static void _hoc_vtrap(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = vtrap ( _threadargs_, *getarg(1) , *getarg(2) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ p = p0; { rates ( _threadargscomma_ v ) ; p = pinf ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V ena = _ion_ena; initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { gna = gnamax * p * p * p ; ina = gna * ( v - ena ) ; } _current += ina; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V ena = _ion_ena; _g = _nrn_current(_threadargs_, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_threadargs_, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { ena = _ion_ena; { states(_threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*1); _dlist1 = (int*)malloc(sizeof(int)*1); _slist1[0] = &(p) - _p; _dlist1[0] = &(Dp) - _p; #pragma acc enter data copyin(_slist1[0:1]) #pragma acc enter data copyin(_dlist1[0:1]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/SynNMDA10_1.cpp000066400000000000000000001203221425457616700227550ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:2] , _slist1[0:10], _dlist1[0:10] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #if !defined(NET_RECEIVE_BUFFERING) #define NET_RECEIVE_BUFFERING 1 #endif #define nrn_init _nrn_init__NMDA10_1 #define nrn_cur _nrn_cur__NMDA10_1 #define _nrn_current _nrn_current__NMDA10_1 #define nrn_jacob _nrn_jacob__NMDA10_1 #define nrn_state _nrn_state__NMDA10_1 #define initmodel initmodel__NMDA10_1 #define _net_receive _net_receive__NMDA10_1 #define _net_init _net_init__NMDA10_1 #define nrn_state_launcher nrn_state_NMDA10_1_launcher #define nrn_cur_launcher nrn_cur_NMDA10_1_launcher #define nrn_jacob_launcher nrn_jacob_NMDA10_1_launcher #if NET_RECEIVE_BUFFERING #define _net_buf_receive _net_buf_receive_NMDA10_1 void _net_buf_receive(NrnThread*); #endif #define kstates kstates_NMDA10_1 #define release release_NMDA10_1 #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define Erev _p[0*_STRIDE] #define gmax _p[1*_STRIDE] #define tau _p[2*_STRIDE] #define T_max _p[3*_STRIDE] #define i _p[4*_STRIDE] #define g _p[5*_STRIDE] #define T _p[6*_STRIDE] #define tRel _p[7*_STRIDE] #define synon _p[8*_STRIDE] #define rb _p[9*_STRIDE] #define rmb _p[10*_STRIDE] #define rmu _p[11*_STRIDE] #define rbMg _p[12*_STRIDE] #define rmc1b _p[13*_STRIDE] #define rmc1u _p[14*_STRIDE] #define rmc2b _p[15*_STRIDE] #define rmc2u _p[16*_STRIDE] #define rmd1b _p[17*_STRIDE] #define rmd1u _p[18*_STRIDE] #define rmd2b _p[19*_STRIDE] #define rmd2u _p[20*_STRIDE] #define U _p[21*_STRIDE] #define Cl _p[22*_STRIDE] #define D1 _p[23*_STRIDE] #define D2 _p[24*_STRIDE] #define O _p[25*_STRIDE] #define UMg _p[26*_STRIDE] #define ClMg _p[27*_STRIDE] #define D1Mg _p[28*_STRIDE] #define D2Mg _p[29*_STRIDE] #define OMg _p[30*_STRIDE] #define w _p[31*_STRIDE] #define DU _p[32*_STRIDE] #define DCl _p[33*_STRIDE] #define DD1 _p[34*_STRIDE] #define DD2 _p[35*_STRIDE] #define DO _p[36*_STRIDE] #define DUMg _p[37*_STRIDE] #define DClMg _p[38*_STRIDE] #define DD1Mg _p[39*_STRIDE] #define DD2Mg _p[40*_STRIDE] #define DOMg _p[41*_STRIDE] #define _v_unused _p[42*_STRIDE] #define _g_unused _p[43*_STRIDE] #define _tsav _p[44*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _nd_area _nt_data[_ppvar[0*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static double _hoc_release(); #endif /*BBCORE*/ static int _mechtype; static int _pointtype; #if 0 /*BBCORE*/ static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process(); return create_point_process(_pointtype, _ho); } static void _hoc_destroy_pnt(); static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process(); return loc_point_process(_pointtype, _vptr); } static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point(); return has_loc_point(_vptr); } static double _hoc_get_loc_pnt(_vptr)void* _vptr; { double get_loc_point_process(); return (get_loc_point_process(_vptr)); } #endif /*BBCORE*/ #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { 0,0 }; static Member_func _member_func[] = { "loc", _hoc_loc_pnt, "has_loc", _hoc_has_loc, "get_loc", _hoc_get_loc_pnt, "release", _hoc_release, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ #define Rmc2u Rmc2u_NMDA10_1 double Rmc2u = 0.00504192; #pragma acc declare copyin (Rmc2u) #define Rmc2b Rmc2b_NMDA10_1 double Rmc2b = 5e-05; #pragma acc declare copyin (Rmc2b) #define Rmc1u Rmc1u_NMDA10_1 double Rmc1u = 0.00243831; #pragma acc declare copyin (Rmc1u) #define Rmc1b Rmc1b_NMDA10_1 double Rmc1b = 5e-05; #pragma acc declare copyin (Rmc1b) #define Rmd2u Rmd2u_NMDA10_1 double Rmd2u = 0.00295341; #pragma acc declare copyin (Rmd2u) #define Rmd2b Rmd2b_NMDA10_1 double Rmd2b = 5e-05; #pragma acc declare copyin (Rmd2b) #define Rmd1u Rmd1u_NMDA10_1 double Rmd1u = 0.00298874; #pragma acc declare copyin (Rmd1u) #define Rmd1b Rmd1b_NMDA10_1 double Rmd1b = 5e-05; #pragma acc declare copyin (Rmd1b) #define RcMg RcMg_NMDA10_1 double RcMg = 0.548; #pragma acc declare copyin (RcMg) #define RoMg RoMg_NMDA10_1 double RoMg = 0.01; #pragma acc declare copyin (RoMg) #define Rr2Mg Rr2Mg_NMDA10_1 double Rr2Mg = 0.00042; #pragma acc declare copyin (Rr2Mg) #define Rd2Mg Rd2Mg_NMDA10_1 double Rd2Mg = 0.00026; #pragma acc declare copyin (Rd2Mg) #define Rr1Mg Rr1Mg_NMDA10_1 double Rr1Mg = 0.00087; #pragma acc declare copyin (Rr1Mg) #define Rd1Mg Rd1Mg_NMDA10_1 double Rd1Mg = 0.0021; #pragma acc declare copyin (Rd1Mg) #define RuMg RuMg_NMDA10_1 double RuMg = 0.0171; #pragma acc declare copyin (RuMg) #define RbMg RbMg_NMDA10_1 double RbMg = 10; #pragma acc declare copyin (RbMg) #define Rmu Rmu_NMDA10_1 double Rmu = 12.8; #pragma acc declare copyin (Rmu) #define Rmb Rmb_NMDA10_1 double Rmb = 0.05; #pragma acc declare copyin (Rmb) #define Rc Rc_NMDA10_1 double Rc = 0.273; #pragma acc declare copyin (Rc) #define Ro Ro_NMDA10_1 double Ro = 0.01; #pragma acc declare copyin (Ro) #define Rr2 Rr2_NMDA10_1 double Rr2 = 0.0005; #pragma acc declare copyin (Rr2) #define Rd2 Rd2_NMDA10_1 double Rd2 = 0.00043; #pragma acc declare copyin (Rd2) #define Rr1 Rr1_NMDA10_1 double Rr1 = 0.0016; #pragma acc declare copyin (Rr1) #define Rd1 Rd1_NMDA10_1 double Rd1 = 0.0022; #pragma acc declare copyin (Rd1) #define Ru Ru_NMDA10_1 double Ru = 0.0056; #pragma acc declare copyin (Ru) #define Rb Rb_NMDA10_1 double Rb = 10; #pragma acc declare copyin (Rb) #define memb_fraction memb_fraction_NMDA10_1 double memb_fraction = 0.8; #pragma acc declare copyin (memb_fraction) #define mg mg_NMDA10_1 double mg = 1; #pragma acc declare copyin (mg) #define valence valence_NMDA10_1 double valence = -2; #pragma acc declare copyin (valence) static void _acc_globals_update() { #pragma acc update device (Rmc2u) if(nrn_threads->compute_gpu) #pragma acc update device (Rmc2b) if(nrn_threads->compute_gpu) #pragma acc update device (Rmc1u) if(nrn_threads->compute_gpu) #pragma acc update device (Rmc1b) if(nrn_threads->compute_gpu) #pragma acc update device (Rmd2u) if(nrn_threads->compute_gpu) #pragma acc update device (Rmd2b) if(nrn_threads->compute_gpu) #pragma acc update device (Rmd1u) if(nrn_threads->compute_gpu) #pragma acc update device (Rmd1b) if(nrn_threads->compute_gpu) #pragma acc update device (RcMg) if(nrn_threads->compute_gpu) #pragma acc update device (RoMg) if(nrn_threads->compute_gpu) #pragma acc update device (Rr2Mg) if(nrn_threads->compute_gpu) #pragma acc update device (Rd2Mg) if(nrn_threads->compute_gpu) #pragma acc update device (Rr1Mg) if(nrn_threads->compute_gpu) #pragma acc update device (Rd1Mg) if(nrn_threads->compute_gpu) #pragma acc update device (RuMg) if(nrn_threads->compute_gpu) #pragma acc update device (RbMg) if(nrn_threads->compute_gpu) #pragma acc update device (Rmu) if(nrn_threads->compute_gpu) #pragma acc update device (Rmb) if(nrn_threads->compute_gpu) #pragma acc update device (Rc) if(nrn_threads->compute_gpu) #pragma acc update device (Ro) if(nrn_threads->compute_gpu) #pragma acc update device (Rr2) if(nrn_threads->compute_gpu) #pragma acc update device (Rd2) if(nrn_threads->compute_gpu) #pragma acc update device (Rr1) if(nrn_threads->compute_gpu) #pragma acc update device (Rd1) if(nrn_threads->compute_gpu) #pragma acc update device (Ru) if(nrn_threads->compute_gpu) #pragma acc update device (Rb) if(nrn_threads->compute_gpu) #pragma acc update device (memb_fraction) if(nrn_threads->compute_gpu) #pragma acc update device (mg) if(nrn_threads->compute_gpu) #pragma acc update device (valence) if(nrn_threads->compute_gpu) } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "tau", 1e-09, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "mg_NMDA10_1", "mM", "Rb_NMDA10_1", "/mM", "Ru_NMDA10_1", "/ms", "Ro_NMDA10_1", "/ms", "Rc_NMDA10_1", "/ms", "Rd1_NMDA10_1", "/ms", "Rr1_NMDA10_1", "/ms", "Rd2_NMDA10_1", "/ms", "Rr2_NMDA10_1", "/ms", "Rmb_NMDA10_1", "/mM", "Rmu_NMDA10_1", "/ms", "Rmc1b_NMDA10_1", "/mM", "Rmc1u_NMDA10_1", "/ms", "Rmc2b_NMDA10_1", "/mM", "Rmc2u_NMDA10_1", "/ms", "Rmd1b_NMDA10_1", "/mM", "Rmd1u_NMDA10_1", "/ms", "Rmd2b_NMDA10_1", "/mM", "Rmd2u_NMDA10_1", "/ms", "RbMg_NMDA10_1", "/mM", "RuMg_NMDA10_1", "/ms", "RoMg_NMDA10_1", "/ms", "RcMg_NMDA10_1", "/ms", "Rd1Mg_NMDA10_1", "/ms", "Rr1Mg_NMDA10_1", "/ms", "Rd2Mg_NMDA10_1", "/ms", "Rr2Mg_NMDA10_1", "/ms", "Erev", "mV", "gmax", "pS", "tau", "ms", "T_max", "mM", "i", "nA", "g", "uS", "T", "mM", "tRel", "ms", "rb", "/ms", "rmb", "/ms", "rmu", "/ms", "rbMg", "/ms", "rmc1b", "/ms", "rmc1u", "/ms", "rmc2b", "/ms", "rmc2u", "/ms", "rmd1b", "/ms", "rmd1u", "/ms", "rmd2b", "/ms", "rmd2u", "/ms", 0,0 }; #endif /*BBCORE*/ static double ClMg0 = 0; #pragma acc declare copyin(ClMg0) static double Cl0 = 0; #pragma acc declare copyin(Cl0) static double D2Mg0 = 0; #pragma acc declare copyin(D2Mg0) static double D1Mg0 = 0; #pragma acc declare copyin(D1Mg0) static double D20 = 0; #pragma acc declare copyin(D20) static double D10 = 0; #pragma acc declare copyin(D10) static double OMg0 = 0; #pragma acc declare copyin(OMg0) static double O0 = 0; #pragma acc declare copyin(O0) static double UMg0 = 0; #pragma acc declare copyin(UMg0) static double U0 = 0; #pragma acc declare copyin(U0) static double delta_t = 1; #pragma acc declare copyin(delta_t) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "mg_NMDA10_1", &mg_NMDA10_1, "valence_NMDA10_1", &valence_NMDA10_1, "memb_fraction_NMDA10_1", &memb_fraction_NMDA10_1, "Rb_NMDA10_1", &Rb_NMDA10_1, "Ru_NMDA10_1", &Ru_NMDA10_1, "Ro_NMDA10_1", &Ro_NMDA10_1, "Rc_NMDA10_1", &Rc_NMDA10_1, "Rd1_NMDA10_1", &Rd1_NMDA10_1, "Rr1_NMDA10_1", &Rr1_NMDA10_1, "Rd2_NMDA10_1", &Rd2_NMDA10_1, "Rr2_NMDA10_1", &Rr2_NMDA10_1, "Rmb_NMDA10_1", &Rmb_NMDA10_1, "Rmu_NMDA10_1", &Rmu_NMDA10_1, "Rmc1b_NMDA10_1", &Rmc1b_NMDA10_1, "Rmc1u_NMDA10_1", &Rmc1u_NMDA10_1, "Rmc2b_NMDA10_1", &Rmc2b_NMDA10_1, "Rmc2u_NMDA10_1", &Rmc2u_NMDA10_1, "Rmd1b_NMDA10_1", &Rmd1b_NMDA10_1, "Rmd1u_NMDA10_1", &Rmd1u_NMDA10_1, "Rmd2b_NMDA10_1", &Rmd2b_NMDA10_1, "Rmd2u_NMDA10_1", &Rmd2u_NMDA10_1, "RbMg_NMDA10_1", &RbMg_NMDA10_1, "RuMg_NMDA10_1", &RuMg_NMDA10_1, "RoMg_NMDA10_1", &RoMg_NMDA10_1, "RcMg_NMDA10_1", &RcMg_NMDA10_1, "Rd1Mg_NMDA10_1", &Rd1Mg_NMDA10_1, "Rr1Mg_NMDA10_1", &Rr1Mg_NMDA10_1, "Rd2Mg_NMDA10_1", &Rd2Mg_NMDA10_1, "Rr2Mg_NMDA10_1", &Rr2Mg_NMDA10_1, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); #if 0 /*BBCORE*/ static void _hoc_destroy_pnt(_vptr) void* _vptr; { destroy_point_process(_vptr); } #endif /*BBCORE*/ /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NMDA10_1", "Erev", "gmax", "tau", "T_max", 0, "i", "g", "T", "tRel", "synon", "rb", "rmb", "rmu", "rbMg", "rmc1b", "rmc1u", "rmc2b", "rmc2u", "rmd1b", "rmd1u", "rmd2b", "rmd2u", 0, "U", "Cl", "D1", "D2", "O", "UMg", "ClMg", "D1Mg", "D2Mg", "OMg", 0, 0}; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ Erev = 0; gmax = 50; tau = 0.3; T_max = 1.5; #endif /* BBCORE */ } static void _initlists(); void _net_receive(Point_process*, int, double); static void _thread_cleanup(ThreadDatum*); #define _psize 45 #define _ppsize 2 void _SynNMDA10_1_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); #if 0 /*BBCORE*/ #endif /*BBCORE*/ _pointtype = point_register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/ 3); _extcall_thread = (ThreadDatum*)ecalloc(2, sizeof(ThreadDatum)); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "area"); hoc_register_dparam_semantics(_mechtype, 1, "pntproc"); #if NET_RECEIVE_BUFFERING hoc_register_net_receive_buffering(_net_buf_receive, _mechtype); #endif set_pnt_receive(_mechtype, _net_receive, nullptr, 1); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "kinetic NMDA receptor model"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int release(_threadargsprotocomma_ double); #define _MATELM1(_row,_col) _nrn_thread_getelm((SparseObj*)_so, _row + 1, _col + 1, _iml)[_iml] #define _RHS1(_arg) _rhs[(_arg+1)*_STRIDE] #define _linmat1 1 static int _spth1 = 1; static int _cvspth1 = 0; static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_NMDA10_1 int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NMDA10_1 int* _dlist1; #pragma acc declare create(_dlist1) /* _kinetic_ kstates _NMDA10_1 */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct kstates_NMDA10_1 { int operator()(SparseObj* _so, double* _rhs, _threadargsproto_) const; }; int kstates_NMDA10_1::operator() (SparseObj* _so, double* _rhs, _threadargsproto_) const {int _reset=0; { double b_flux, f_flux, _term; int _i; {int _i; double _dt1 = 1.0/dt; for(_i=1;_i<10;_i++){ _RHS1(_i) = -_dt1*(_p[_slist1[_i]*_STRIDE] - _p[_dlist1[_i]*_STRIDE]); _MATELM1(_i, _i) = _dt1; } } release ( _threadargscomma_ t ) ; rb = Rb * T ; rbMg = RbMg * T ; rmb = Rmb * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmu = Rmu * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmc1b = Rmc1b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmc1u = Rmc1u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmc2b = Rmc2b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmc2u = Rmc2u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmd1b = Rmd1b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmd1u = Rmd1u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmd2b = Rmd2b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmd2u = Rmd2u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; /* ~ U <-> Cl ( rb , Ru )*/ f_flux = rb * U ; b_flux = Ru * Cl ; _RHS1( 9) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = rb ; _MATELM1( 9 ,9) += _term; _MATELM1( 2 ,9) -= _term; _term = Ru ; _MATELM1( 9 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ Cl <-> O ( Ro , Rc )*/ f_flux = Ro * Cl ; b_flux = Rc * O ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 7) += (f_flux - b_flux); _term = Ro ; _MATELM1( 2 ,2) += _term; _MATELM1( 7 ,2) -= _term; _term = Rc ; _MATELM1( 2 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ Cl <-> D1 ( Rd1 , Rr1 )*/ f_flux = Rd1 * Cl ; b_flux = Rr1 * D1 ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 6) += (f_flux - b_flux); _term = Rd1 ; _MATELM1( 2 ,2) += _term; _MATELM1( 6 ,2) -= _term; _term = Rr1 ; _MATELM1( 2 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ D1 <-> D2 ( Rd2 , Rr2 )*/ f_flux = Rd2 * D1 ; b_flux = Rr2 * D2 ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 5) += (f_flux - b_flux); _term = Rd2 ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = Rr2 ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ O <-> OMg ( rmb , rmu )*/ f_flux = rmb * O ; b_flux = rmu * OMg ; _RHS1( 7) -= (f_flux - b_flux); _term = rmb ; _MATELM1( 7 ,7) += _term; _term = rmu ; _MATELM1( 7 ,0) -= _term; /*REACTION*/ /* ~ UMg <-> ClMg ( rbMg , RuMg )*/ f_flux = rbMg * UMg ; b_flux = RuMg * ClMg ; _RHS1( 8) -= (f_flux - b_flux); _RHS1( 1) += (f_flux - b_flux); _term = rbMg ; _MATELM1( 8 ,8) += _term; _MATELM1( 1 ,8) -= _term; _term = RuMg ; _MATELM1( 8 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ ClMg <-> OMg ( RoMg , RcMg )*/ f_flux = RoMg * ClMg ; b_flux = RcMg * OMg ; _RHS1( 1) -= (f_flux - b_flux); _term = RoMg ; _MATELM1( 1 ,1) += _term; _term = RcMg ; _MATELM1( 1 ,0) -= _term; /*REACTION*/ /* ~ ClMg <-> D1Mg ( Rd1Mg , Rr1Mg )*/ f_flux = Rd1Mg * ClMg ; b_flux = Rr1Mg * D1Mg ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 4) += (f_flux - b_flux); _term = Rd1Mg ; _MATELM1( 1 ,1) += _term; _MATELM1( 4 ,1) -= _term; _term = Rr1Mg ; _MATELM1( 1 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ D1Mg <-> D2Mg ( Rd2Mg , Rr2Mg )*/ f_flux = Rd2Mg * D1Mg ; b_flux = Rr2Mg * D2Mg ; _RHS1( 4) -= (f_flux - b_flux); _RHS1( 3) += (f_flux - b_flux); _term = Rd2Mg ; _MATELM1( 4 ,4) += _term; _MATELM1( 3 ,4) -= _term; _term = Rr2Mg ; _MATELM1( 4 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* ~ U <-> UMg ( rmc1b , rmc1u )*/ f_flux = rmc1b * U ; b_flux = rmc1u * UMg ; _RHS1( 9) -= (f_flux - b_flux); _RHS1( 8) += (f_flux - b_flux); _term = rmc1b ; _MATELM1( 9 ,9) += _term; _MATELM1( 8 ,9) -= _term; _term = rmc1u ; _MATELM1( 9 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* ~ Cl <-> ClMg ( rmc2b , rmc2u )*/ f_flux = rmc2b * Cl ; b_flux = rmc2u * ClMg ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 1) += (f_flux - b_flux); _term = rmc2b ; _MATELM1( 2 ,2) += _term; _MATELM1( 1 ,2) -= _term; _term = rmc2u ; _MATELM1( 2 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ D1 <-> D1Mg ( rmd1b , rmd1u )*/ f_flux = rmd1b * D1 ; b_flux = rmd1u * D1Mg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 4) += (f_flux - b_flux); _term = rmd1b ; _MATELM1( 6 ,6) += _term; _MATELM1( 4 ,6) -= _term; _term = rmd1u ; _MATELM1( 6 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ D2 <-> D2Mg ( rmd2b , rmd2u )*/ f_flux = rmd2b * D2 ; b_flux = rmd2u * D2Mg ; _RHS1( 5) -= (f_flux - b_flux); _RHS1( 3) += (f_flux - b_flux); _term = rmd2b ; _MATELM1( 5 ,5) += _term; _MATELM1( 3 ,5) -= _term; _term = rmd2u ; _MATELM1( 5 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* U + Cl + D1 + D2 + O + UMg + ClMg + D1Mg + D2Mg + OMg = 1.0 */ _RHS1(0) = 1.0; _MATELM1(0, 0) = 1; _RHS1(0) -= OMg ; _MATELM1(0, 3) = 1; _RHS1(0) -= D2Mg ; _MATELM1(0, 4) = 1; _RHS1(0) -= D1Mg ; _MATELM1(0, 1) = 1; _RHS1(0) -= ClMg ; _MATELM1(0, 8) = 1; _RHS1(0) -= UMg ; _MATELM1(0, 7) = 1; _RHS1(0) -= O ; _MATELM1(0, 5) = 1; _RHS1(0) -= D2 ; _MATELM1(0, 6) = 1; _RHS1(0) -= D1 ; _MATELM1(0, 2) = 1; _RHS1(0) -= Cl ; _MATELM1(0, 9) = 1; _RHS1(0) -= U ; /*CONSERVATION*/ } return _reset; } #if NET_RECEIVE_BUFFERING #undef t #define t _nrb_t static inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag); void _net_buf_receive(NrnThread* _nt) { if (!_nt->_ml_list) { return; } Memb_list* _ml = _nt->_ml_list[_mechtype]; if (!_ml) { return; } NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer; int _di; int stream_id = _nt->stream_id; Point_process* _pnt = _nt->pntprocs; int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset; int _displ_cnt = _nrb->_displ_cnt; _PRAGMA_FOR_NETRECV_ACC_LOOP_ for (_di = 0; _di < _displ_cnt; ++_di) { int _inrb; int _di0 = _nrb->_displ[_di]; int _di1 = _nrb->_displ[_di + 1]; for (_inrb = _di0; _inrb < _di1; ++_inrb) { int _i = _nrb->_nrb_index[_inrb]; int _j = _nrb->_pnt_index[_i]; int _k = _nrb->_weight_index[_i]; double _nrt = _nrb->_nrb_t[_i]; double _nrflag = _nrb->_nrb_flag[_i]; _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag); } } #pragma acc wait(stream_id) _nrb->_displ_cnt = 0; _nrb->_cnt = 0; /*printf("_net_buf_receive__NMDA10_1 %d\n", _nt->_id);*/ } void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) { NrnThread* _nt = nrn_threads + _pnt->_tid; NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer; if (_nrb->_cnt >= _nrb->_size){ realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]); } _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs; _nrb->_weight_index[_nrb->_cnt] = _weight_index; _nrb->_nrb_t[_nrb->_cnt] = _nt->_t; _nrb->_nrb_flag[_nrb->_cnt] = _lflag; ++_nrb->_cnt; } static void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag) #else void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) #endif { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0; Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args; NrnThread* _nt; int _tid = _pnt->_tid; _nt = nrn_threads + _tid; _thread = (ThreadDatum*)0; double *_weights = _nt->_weights; _args = _weights + _weight_index; _ml = _nt->_ml_list[_pnt->_type]; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _iml = _pnt->_i_instance; #if LAYOUT == 1 /*AoS*/ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #endif #if LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; #endif #if LAYOUT > 1 /*AoSoA*/ #error AoSoA not implemented. #endif #if !defined(_OPENACC) assert(_tsav <= t); #endif _tsav = t; { if ( _lflag == 0.0 ) { tRel = t ; synon = 1.0 ; w = _args[0] ; } } #if NET_RECEIVE_BUFFERING #undef t #define t _nt->_t #endif } static int release ( _threadargsprotocomma_ double _lt ) { T = T_max * ( _lt - tRel ) / tau * exp ( 1.0 - ( _lt - tRel ) / tau ) * synon ; return 0; } #if 0 /*BBCORE*/ static double _hoc_release(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; release ( _threadargs_, *getarg(1) ); return(_r); } #endif /*BBCORE*/ /*CVODE ode begin*/ static int _ode_spec1(_threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; {int _i; for(_i=0;_i<10;_i++) _p[_dlist1[_i]] = 0.0;} release ( _threadargscomma_ t ) ; rb = Rb * T ; rbMg = RbMg * T ; rmb = Rmb * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmu = Rmu * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmc1b = Rmc1b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmc1u = Rmc1u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmc2b = Rmc2b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmc2u = Rmc2u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmd1b = Rmd1b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmd1u = Rmd1u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmd2b = Rmd2b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmd2u = Rmd2u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; /* ~ U <-> Cl ( rb , Ru )*/ f_flux = rb * U ; b_flux = Ru * Cl ; DU -= (f_flux - b_flux); DCl += (f_flux - b_flux); /*REACTION*/ /* ~ Cl <-> O ( Ro , Rc )*/ f_flux = Ro * Cl ; b_flux = Rc * O ; DCl -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ Cl <-> D1 ( Rd1 , Rr1 )*/ f_flux = Rd1 * Cl ; b_flux = Rr1 * D1 ; DCl -= (f_flux - b_flux); DD1 += (f_flux - b_flux); /*REACTION*/ /* ~ D1 <-> D2 ( Rd2 , Rr2 )*/ f_flux = Rd2 * D1 ; b_flux = Rr2 * D2 ; DD1 -= (f_flux - b_flux); DD2 += (f_flux - b_flux); /*REACTION*/ /* ~ O <-> OMg ( rmb , rmu )*/ f_flux = rmb * O ; b_flux = rmu * OMg ; DO -= (f_flux - b_flux); DOMg += (f_flux - b_flux); /*REACTION*/ /* ~ UMg <-> ClMg ( rbMg , RuMg )*/ f_flux = rbMg * UMg ; b_flux = RuMg * ClMg ; DUMg -= (f_flux - b_flux); DClMg += (f_flux - b_flux); /*REACTION*/ /* ~ ClMg <-> OMg ( RoMg , RcMg )*/ f_flux = RoMg * ClMg ; b_flux = RcMg * OMg ; DClMg -= (f_flux - b_flux); DOMg += (f_flux - b_flux); /*REACTION*/ /* ~ ClMg <-> D1Mg ( Rd1Mg , Rr1Mg )*/ f_flux = Rd1Mg * ClMg ; b_flux = Rr1Mg * D1Mg ; DClMg -= (f_flux - b_flux); DD1Mg += (f_flux - b_flux); /*REACTION*/ /* ~ D1Mg <-> D2Mg ( Rd2Mg , Rr2Mg )*/ f_flux = Rd2Mg * D1Mg ; b_flux = Rr2Mg * D2Mg ; DD1Mg -= (f_flux - b_flux); DD2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ U <-> UMg ( rmc1b , rmc1u )*/ f_flux = rmc1b * U ; b_flux = rmc1u * UMg ; DU -= (f_flux - b_flux); DUMg += (f_flux - b_flux); /*REACTION*/ /* ~ Cl <-> ClMg ( rmc2b , rmc2u )*/ f_flux = rmc2b * Cl ; b_flux = rmc2u * ClMg ; DCl -= (f_flux - b_flux); DClMg += (f_flux - b_flux); /*REACTION*/ /* ~ D1 <-> D1Mg ( rmd1b , rmd1u )*/ f_flux = rmd1b * D1 ; b_flux = rmd1u * D1Mg ; DD1 -= (f_flux - b_flux); DD1Mg += (f_flux - b_flux); /*REACTION*/ /* ~ D2 <-> D2Mg ( rmd2b , rmd2u )*/ f_flux = rmd2b * D2 ; b_flux = rmd2u * D2Mg ; DD2 -= (f_flux - b_flux); DD2Mg += (f_flux - b_flux); /*REACTION*/ /* U + Cl + D1 + D2 + O + UMg + ClMg + D1Mg + D2Mg + OMg = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE matsol*/ static int _ode_matsol1(void* _so, double* _rhs, _threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; b_flux = f_flux = 0.; {int _i; double _dt1 = 1.0/dt; for(_i=0;_i<10;_i++){ _RHS1(_i) = _dt1*(_p[_dlist1[_i]]); _MATELM1(_i, _i) = _dt1; } } release ( _threadargscomma_ t ) ; rb = Rb * T ; rbMg = RbMg * T ; rmb = Rmb * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmu = Rmu * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmc1b = Rmc1b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmc1u = Rmc1u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmc2b = Rmc2b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmc2u = Rmc2u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmd1b = Rmd1b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmd1u = Rmd1u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; rmd2b = Rmd2b * mg * exp ( ( 1.0 * v - 40.0 ) * valence * memb_fraction / 25.0 ) ; rmd2u = Rmd2u * exp ( ( - 1.0 ) * ( v - 40.0 ) * valence * ( 1.0 - memb_fraction ) / 25.0 ) ; /* ~ U <-> Cl ( rb , Ru )*/ _term = rb ; _MATELM1( 9 ,9) += _term; _MATELM1( 2 ,9) -= _term; _term = Ru ; _MATELM1( 9 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ Cl <-> O ( Ro , Rc )*/ _term = Ro ; _MATELM1( 2 ,2) += _term; _MATELM1( 7 ,2) -= _term; _term = Rc ; _MATELM1( 2 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ Cl <-> D1 ( Rd1 , Rr1 )*/ _term = Rd1 ; _MATELM1( 2 ,2) += _term; _MATELM1( 6 ,2) -= _term; _term = Rr1 ; _MATELM1( 2 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ D1 <-> D2 ( Rd2 , Rr2 )*/ _term = Rd2 ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = Rr2 ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ O <-> OMg ( rmb , rmu )*/ _term = rmb ; _MATELM1( 7 ,7) += _term; _MATELM1( 0 ,7) -= _term; _term = rmu ; _MATELM1( 7 ,0) -= _term; _MATELM1( 0 ,0) += _term; /*REACTION*/ /* ~ UMg <-> ClMg ( rbMg , RuMg )*/ _term = rbMg ; _MATELM1( 8 ,8) += _term; _MATELM1( 1 ,8) -= _term; _term = RuMg ; _MATELM1( 8 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ ClMg <-> OMg ( RoMg , RcMg )*/ _term = RoMg ; _MATELM1( 1 ,1) += _term; _MATELM1( 0 ,1) -= _term; _term = RcMg ; _MATELM1( 1 ,0) -= _term; _MATELM1( 0 ,0) += _term; /*REACTION*/ /* ~ ClMg <-> D1Mg ( Rd1Mg , Rr1Mg )*/ _term = Rd1Mg ; _MATELM1( 1 ,1) += _term; _MATELM1( 4 ,1) -= _term; _term = Rr1Mg ; _MATELM1( 1 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ D1Mg <-> D2Mg ( Rd2Mg , Rr2Mg )*/ _term = Rd2Mg ; _MATELM1( 4 ,4) += _term; _MATELM1( 3 ,4) -= _term; _term = Rr2Mg ; _MATELM1( 4 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* ~ U <-> UMg ( rmc1b , rmc1u )*/ _term = rmc1b ; _MATELM1( 9 ,9) += _term; _MATELM1( 8 ,9) -= _term; _term = rmc1u ; _MATELM1( 9 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* ~ Cl <-> ClMg ( rmc2b , rmc2u )*/ _term = rmc2b ; _MATELM1( 2 ,2) += _term; _MATELM1( 1 ,2) -= _term; _term = rmc2u ; _MATELM1( 2 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ D1 <-> D1Mg ( rmd1b , rmd1u )*/ _term = rmd1b ; _MATELM1( 6 ,6) += _term; _MATELM1( 4 ,6) -= _term; _term = rmd1u ; _MATELM1( 6 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ D2 <-> D2Mg ( rmd2b , rmd2u )*/ _term = rmd2b ; _MATELM1( 5 ,5) += _term; _MATELM1( 3 ,5) -= _term; _term = rmd2u ; _MATELM1( 5 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* U + Cl + D1 + D2 + O + UMg + ClMg + D1Mg + D2Mg + OMg = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE end*/ static void _thread_cleanup(ThreadDatum* _thread) { _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_cvspth1]._pvoid); _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_spth1]._pvoid); } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ ClMg = ClMg0; Cl = Cl0; D2Mg = D2Mg0; D1Mg = D1Mg0; D2 = D20; D1 = D10; OMg = OMg0; O = O0; UMg = UMg0; U = U0; { T = 0.0 ; synon = 0.0 ; tRel = 0.0 ; U = 1.0 ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; if (!_thread[_spth1]._pvoid) { _thread[_spth1]._pvoid = nrn_cons_sparseobj(kstates_NMDA10_1{}, 10, _ml, _threadargs_); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_so = (void*) acc_deviceptr(_thread[_spth1]._pvoid); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[_spth1]._pvoid), &_d_so, sizeof(void*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _tsav = -1e20; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { g = w * gmax * O ; i = g * ( v - Erev ) ; } _current += i; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; double * _vec_shadow_rhs = _nt->_shadow_rhs; double * _vec_shadow_d = _nt->_shadow_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V _g = _nrn_current(_threadargs_, _v + .001); { _rhs = _nrn_current(_threadargs_, _v); } _g = (_g - _rhs)/.001; double _mfact = 1.e2/(_nd_area); _g *= _mfact; _rhs *= _mfact; _PRCELLSTATE_G #ifdef _OPENACC if(_nt->compute_gpu) { #pragma acc atomic update _vec_rhs[_nd_idx] -= _rhs; #pragma acc atomic update _vec_d[_nd_idx] += _g; } else { _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; } #else _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; #endif } #ifdef _OPENACC if(!(_nt->compute_gpu)) { for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; } #else for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; #endif } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { { sparse_thread(static_cast(_thread[_spth1]._pvoid), 10, _slist1, _dlist1, &t, dt, kstates_NMDA10_1{}, _linmat1, _threadargs_); }}} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*10); _dlist1 = (int*)malloc(sizeof(int)*10); _slist1[0] = &(OMg) - _p; _dlist1[0] = &(DOMg) - _p; _slist1[1] = &(ClMg) - _p; _dlist1[1] = &(DClMg) - _p; _slist1[2] = &(Cl) - _p; _dlist1[2] = &(DCl) - _p; _slist1[3] = &(D2Mg) - _p; _dlist1[3] = &(DD2Mg) - _p; _slist1[4] = &(D1Mg) - _p; _dlist1[4] = &(DD1Mg) - _p; _slist1[5] = &(D2) - _p; _dlist1[5] = &(DD2) - _p; _slist1[6] = &(D1) - _p; _dlist1[6] = &(DD1) - _p; _slist1[7] = &(O) - _p; _dlist1[7] = &(DO) - _p; _slist1[8] = &(UMg) - _p; _dlist1[8] = &(DUMg) - _p; _slist1[9] = &(U) - _p; _dlist1[9] = &(DU) - _p; #pragma acc enter data copyin(_slist1[0:10]) #pragma acc enter data copyin(_dlist1[0:10]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/SynNMDA10_2.cpp000066400000000000000000000757621425457616700227770ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:2] , _slist1[0:10], _dlist1[0:10] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #if !defined(NET_RECEIVE_BUFFERING) #define NET_RECEIVE_BUFFERING 1 #endif #define nrn_init _nrn_init__NMDA10_2 #define nrn_cur _nrn_cur__NMDA10_2 #define _nrn_current _nrn_current__NMDA10_2 #define nrn_jacob _nrn_jacob__NMDA10_2 #define nrn_state _nrn_state__NMDA10_2 #define initmodel initmodel__NMDA10_2 #define _net_receive _net_receive__NMDA10_2 #define _net_init _net_init__NMDA10_2 #define nrn_state_launcher nrn_state_NMDA10_2_launcher #define nrn_cur_launcher nrn_cur_NMDA10_2_launcher #define nrn_jacob_launcher nrn_jacob_NMDA10_2_launcher #if NET_RECEIVE_BUFFERING #define _net_buf_receive _net_buf_receive_NMDA10_2 void _net_buf_receive(NrnThread*); #endif #define kstates kstates_NMDA10_2 #define release release_NMDA10_2 #define rates rates_NMDA10_2 #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define Erev _p[0*_STRIDE] #define gmax _p[1*_STRIDE] #define tau _p[2*_STRIDE] #define T_max _p[3*_STRIDE] #define i _p[4*_STRIDE] #define g _p[5*_STRIDE] #define rb _p[6*_STRIDE] #define rbb _p[7*_STRIDE] #define RMgB _p[8*_STRIDE] #define RMgU _p[9*_STRIDE] #define T _p[10*_STRIDE] #define tRel _p[11*_STRIDE] #define synon _p[12*_STRIDE] #define C0 _p[13*_STRIDE] #define C1 _p[14*_STRIDE] #define C2 _p[15*_STRIDE] #define D _p[16*_STRIDE] #define O _p[17*_STRIDE] #define CB0 _p[18*_STRIDE] #define CB1 _p[19*_STRIDE] #define CB2 _p[20*_STRIDE] #define DB _p[21*_STRIDE] #define OB _p[22*_STRIDE] #define w _p[23*_STRIDE] #define DC0 _p[24*_STRIDE] #define DC1 _p[25*_STRIDE] #define DC2 _p[26*_STRIDE] #define DD _p[27*_STRIDE] #define DO _p[28*_STRIDE] #define DCB0 _p[29*_STRIDE] #define DCB1 _p[30*_STRIDE] #define DCB2 _p[31*_STRIDE] #define DDB _p[32*_STRIDE] #define DOB _p[33*_STRIDE] #define _v_unused _p[34*_STRIDE] #define _g_unused _p[35*_STRIDE] #define _tsav _p[36*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _nd_area _nt_data[_ppvar[0*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static double _hoc_release(); static double _hoc_rates(); #endif /*BBCORE*/ static int _mechtype; static int _pointtype; #if 0 /*BBCORE*/ static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process(); return create_point_process(_pointtype, _ho); } static void _hoc_destroy_pnt(); static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process(); return loc_point_process(_pointtype, _vptr); } static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point(); return has_loc_point(_vptr); } static double _hoc_get_loc_pnt(_vptr)void* _vptr; { double get_loc_point_process(); return (get_loc_point_process(_vptr)); } #endif /*BBCORE*/ #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { 0,0 }; static Member_func _member_func[] = { "loc", _hoc_loc_pnt, "has_loc", _hoc_has_loc, "get_loc", _hoc_get_loc_pnt, "release", _hoc_release, "rates", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ #define Rc Rc_NMDA10_2 double Rc = 0.0916; #pragma acc declare copyin (Rc) #define Ro Ro_NMDA10_2 double Ro = 0.0465; #pragma acc declare copyin (Ro) #define Rr Rr_NMDA10_2 double Rr = 0.0018; #pragma acc declare copyin (Rr) #define Rd Rd_NMDA10_2 double Rd = 0.0084; #pragma acc declare copyin (Rd) #define Ru Ru_NMDA10_2 double Ru = 0.0055; #pragma acc declare copyin (Ru) #define Rb Rb_NMDA10_2 double Rb = 5; #pragma acc declare copyin (Rb) #define mg mg_NMDA10_2 double mg = 1; #pragma acc declare copyin (mg) static void _acc_globals_update() { #pragma acc update device (Rc) if(nrn_threads->compute_gpu) #pragma acc update device (Ro) if(nrn_threads->compute_gpu) #pragma acc update device (Rr) if(nrn_threads->compute_gpu) #pragma acc update device (Rd) if(nrn_threads->compute_gpu) #pragma acc update device (Ru) if(nrn_threads->compute_gpu) #pragma acc update device (Rb) if(nrn_threads->compute_gpu) #pragma acc update device (mg) if(nrn_threads->compute_gpu) } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "tau", 1e-09, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "mg_NMDA10_2", "mM", "Rb_NMDA10_2", "/mM", "Ru_NMDA10_2", "/ms", "Rd_NMDA10_2", "/ms", "Rr_NMDA10_2", "/ms", "Ro_NMDA10_2", "/ms", "Rc_NMDA10_2", "/ms", "Erev", "mV", "gmax", "pS", "tau", "ms", "T_max", "mM", "i", "nA", "g", "uS", "rb", "/ms", "rbb", "/ms", "RMgB", "/ms", "RMgU", "/ms", "T", "mM", "tRel", "ms", 0,0 }; #endif /*BBCORE*/ static double CB20 = 0; #pragma acc declare copyin(CB20) static double CB10 = 0; #pragma acc declare copyin(CB10) static double CB00 = 0; #pragma acc declare copyin(CB00) static double C20 = 0; #pragma acc declare copyin(C20) static double C10 = 0; #pragma acc declare copyin(C10) static double C00 = 0; #pragma acc declare copyin(C00) static double DB0 = 0; #pragma acc declare copyin(DB0) static double D0 = 0; #pragma acc declare copyin(D0) static double OB0 = 0; #pragma acc declare copyin(OB0) static double O0 = 0; #pragma acc declare copyin(O0) static double delta_t = 1; #pragma acc declare copyin(delta_t) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "mg_NMDA10_2", &mg_NMDA10_2, "Rb_NMDA10_2", &Rb_NMDA10_2, "Ru_NMDA10_2", &Ru_NMDA10_2, "Rd_NMDA10_2", &Rd_NMDA10_2, "Rr_NMDA10_2", &Rr_NMDA10_2, "Ro_NMDA10_2", &Ro_NMDA10_2, "Rc_NMDA10_2", &Rc_NMDA10_2, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); #if 0 /*BBCORE*/ static void _hoc_destroy_pnt(_vptr) void* _vptr; { destroy_point_process(_vptr); } #endif /*BBCORE*/ /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NMDA10_2", "Erev", "gmax", "tau", "T_max", 0, "i", "g", "rb", "rbb", "RMgB", "RMgU", "T", "tRel", "synon", 0, "C0", "C1", "C2", "D", "O", "CB0", "CB1", "CB2", "DB", "OB", 0, 0}; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ Erev = -0.7; gmax = 50; tau = 0.3; T_max = 1.5; #endif /* BBCORE */ } static void _initlists(); void _net_receive(Point_process*, int, double); static void _thread_cleanup(ThreadDatum*); #define _psize 37 #define _ppsize 2 void _SynNMDA10_2_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); #if 0 /*BBCORE*/ #endif /*BBCORE*/ _pointtype = point_register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/ 3); _extcall_thread = (ThreadDatum*)ecalloc(2, sizeof(ThreadDatum)); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "area"); hoc_register_dparam_semantics(_mechtype, 1, "pntproc"); #if NET_RECEIVE_BUFFERING hoc_register_net_receive_buffering(_net_buf_receive, _mechtype); #endif set_pnt_receive(_mechtype, _net_receive, nullptr, 1); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "detailed model of glutamate NMDA receptors"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int release(_threadargsprotocomma_ double); static inline int rates(_threadargsprotocomma_ double); #define _MATELM1(_row,_col) _nrn_thread_getelm((SparseObj*)_so, _row + 1, _col + 1, _iml)[_iml] #define _RHS1(_arg) _rhs[(_arg+1)*_STRIDE] #define _linmat1 1 static int _spth1 = 1; static int _cvspth1 = 0; static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_NMDA10_2 int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NMDA10_2 int* _dlist1; #pragma acc declare create(_dlist1) /* _kinetic_ kstates _NMDA10_2 */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct kstates_NMDA10_2 { int operator()(SparseObj* _so, double* _rhs, _threadargsproto_) const; }; int kstates_NMDA10_2::operator() (SparseObj* _so, double* _rhs, _threadargsproto_) const {int _reset=0; { double b_flux, f_flux, _term; int _i; {int _i; double _dt1 = 1.0/dt; for(_i=1;_i<10;_i++){ _RHS1(_i) = -_dt1*(_p[_slist1[_i]*_STRIDE] - _p[_dlist1[_i]*_STRIDE]); _MATELM1(_i, _i) = _dt1; } } release ( _threadargscomma_ t ) ; rb = Rb * T ; rates ( _threadargscomma_ v ) ; /* ~ C0 <-> C1 ( ( 2.0 * rb ) , Ru )*/ f_flux = ( 2.0 * rb ) * C0 ; b_flux = Ru * C1 ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 5) += (f_flux - b_flux); _term = ( 2.0 * rb ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = Ru ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ C1 <-> C2 ( rb , ( 2.0 * Ru ) )*/ f_flux = rb * C1 ; b_flux = ( 2.0 * Ru ) * C2 ; _RHS1( 5) -= (f_flux - b_flux); _RHS1( 4) += (f_flux - b_flux); _term = rb ; _MATELM1( 5 ,5) += _term; _MATELM1( 4 ,5) -= _term; _term = ( 2.0 * Ru ) ; _MATELM1( 5 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ C2 <-> D ( Rd , Rr )*/ f_flux = Rd * C2 ; b_flux = Rr * D ; _RHS1( 4) -= (f_flux - b_flux); _RHS1( 8) += (f_flux - b_flux); _term = Rd ; _MATELM1( 4 ,4) += _term; _MATELM1( 8 ,4) -= _term; _term = Rr ; _MATELM1( 4 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* ~ C2 <-> O ( Ro , Rc )*/ f_flux = Ro * C2 ; b_flux = Rc * O ; _RHS1( 4) -= (f_flux - b_flux); _RHS1( 9) += (f_flux - b_flux); _term = Ro ; _MATELM1( 4 ,4) += _term; _MATELM1( 9 ,4) -= _term; _term = Rc ; _MATELM1( 4 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ O <-> OB ( RMgB , RMgU )*/ f_flux = RMgB * O ; b_flux = RMgU * OB ; _RHS1( 9) -= (f_flux - b_flux); _term = RMgB ; _MATELM1( 9 ,9) += _term; _term = RMgU ; _MATELM1( 9 ,0) -= _term; /*REACTION*/ /* ~ OB <-> CB2 ( ( 3.0 * Rc ) , Ro )*/ f_flux = ( 3.0 * Rc ) * OB ; b_flux = Ro * CB2 ; _RHS1( 1) += (f_flux - b_flux); _term = ( 3.0 * Rc ) ; _MATELM1( 1 ,0) -= _term; _term = Ro ; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ CB2 <-> DB ( Rd , Rr )*/ f_flux = Rd * CB2 ; b_flux = Rr * DB ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 7) += (f_flux - b_flux); _term = Rd ; _MATELM1( 1 ,1) += _term; _MATELM1( 7 ,1) -= _term; _term = Rr ; _MATELM1( 1 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ CB2 <-> CB1 ( ( 2.0 * Ru ) , rb )*/ f_flux = ( 2.0 * Ru ) * CB2 ; b_flux = rb * CB1 ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = ( 2.0 * Ru ) ; _MATELM1( 1 ,1) += _term; _MATELM1( 2 ,1) -= _term; _term = rb ; _MATELM1( 1 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ CB1 <-> CB0 ( Ru , ( 2.0 * rb ) )*/ f_flux = Ru * CB1 ; b_flux = ( 2.0 * rb ) * CB0 ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 3) += (f_flux - b_flux); _term = Ru ; _MATELM1( 2 ,2) += _term; _MATELM1( 3 ,2) -= _term; _term = ( 2.0 * rb ) ; _MATELM1( 2 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* C0 + C1 + C2 + D + O + CB0 + CB1 + CB2 + DB + OB = 1.0 */ _RHS1(0) = 1.0; _MATELM1(0, 0) = 1; _RHS1(0) -= OB ; _MATELM1(0, 7) = 1; _RHS1(0) -= DB ; _MATELM1(0, 1) = 1; _RHS1(0) -= CB2 ; _MATELM1(0, 2) = 1; _RHS1(0) -= CB1 ; _MATELM1(0, 3) = 1; _RHS1(0) -= CB0 ; _MATELM1(0, 9) = 1; _RHS1(0) -= O ; _MATELM1(0, 8) = 1; _RHS1(0) -= D ; _MATELM1(0, 4) = 1; _RHS1(0) -= C2 ; _MATELM1(0, 5) = 1; _RHS1(0) -= C1 ; _MATELM1(0, 6) = 1; _RHS1(0) -= C0 ; /*CONSERVATION*/ } return _reset; } #if NET_RECEIVE_BUFFERING #undef t #define t _nrb_t static inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag); void _net_buf_receive(NrnThread* _nt) { if (!_nt->_ml_list) { return; } Memb_list* _ml = _nt->_ml_list[_mechtype]; if (!_ml) { return; } NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer; int _di; int stream_id = _nt->stream_id; Point_process* _pnt = _nt->pntprocs; int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset; int _displ_cnt = _nrb->_displ_cnt; _PRAGMA_FOR_NETRECV_ACC_LOOP_ for (_di = 0; _di < _displ_cnt; ++_di) { int _inrb; int _di0 = _nrb->_displ[_di]; int _di1 = _nrb->_displ[_di + 1]; for (_inrb = _di0; _inrb < _di1; ++_inrb) { int _i = _nrb->_nrb_index[_inrb]; int _j = _nrb->_pnt_index[_i]; int _k = _nrb->_weight_index[_i]; double _nrt = _nrb->_nrb_t[_i]; double _nrflag = _nrb->_nrb_flag[_i]; _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag); } } #pragma acc wait(stream_id) _nrb->_displ_cnt = 0; _nrb->_cnt = 0; /*printf("_net_buf_receive__NMDA10_2 %d\n", _nt->_id);*/ } void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) { NrnThread* _nt = nrn_threads + _pnt->_tid; NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer; if (_nrb->_cnt >= _nrb->_size){ realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]); } _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs; _nrb->_weight_index[_nrb->_cnt] = _weight_index; _nrb->_nrb_t[_nrb->_cnt] = _nt->_t; _nrb->_nrb_flag[_nrb->_cnt] = _lflag; ++_nrb->_cnt; } static void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag) #else void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) #endif { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0; Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args; NrnThread* _nt; int _tid = _pnt->_tid; _nt = nrn_threads + _tid; _thread = (ThreadDatum*)0; double *_weights = _nt->_weights; _args = _weights + _weight_index; _ml = _nt->_ml_list[_pnt->_type]; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _iml = _pnt->_i_instance; #if LAYOUT == 1 /*AoS*/ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #endif #if LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; #endif #if LAYOUT > 1 /*AoSoA*/ #error AoSoA not implemented. #endif #if !defined(_OPENACC) assert(_tsav <= t); #endif _tsav = t; { if ( _lflag == 0.0 ) { tRel = t ; synon = 1.0 ; w = _args[0] ; } } #if NET_RECEIVE_BUFFERING #undef t #define t _nt->_t #endif } static int release ( _threadargsprotocomma_ double _lt ) { T = T_max * ( _lt - tRel ) / tau * exp ( 1.0 - ( _lt - tRel ) / tau ) * synon ; /*VERBATIM*/ return 0; return 0; } #if 0 /*BBCORE*/ static double _hoc_release(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; release ( _threadargs_, *getarg(1) ); return(_r); } #endif /*BBCORE*/ static int rates ( _threadargsprotocomma_ double _lv ) { RMgB = 610e-3 * exp ( 1.0 * - _lv / 17.0 ) * ( mg / 1.0 ) * 1.0 ; RMgU = 5400e-3 * exp ( 1.0 * _lv / 47.0 ) * 1.0 ; return 0; } #if 0 /*BBCORE*/ static double _hoc_rates(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; rates ( _threadargs_, *getarg(1) ); return(_r); } #endif /*BBCORE*/ /*CVODE ode begin*/ static int _ode_spec1(_threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; {int _i; for(_i=0;_i<10;_i++) _p[_dlist1[_i]] = 0.0;} release ( _threadargscomma_ t ) ; rb = Rb * T ; rates ( _threadargscomma_ v ) ; /* ~ C0 <-> C1 ( ( 2.0 * rb ) , Ru )*/ f_flux = ( 2.0 * rb ) * C0 ; b_flux = Ru * C1 ; DC0 -= (f_flux - b_flux); DC1 += (f_flux - b_flux); /*REACTION*/ /* ~ C1 <-> C2 ( rb , ( 2.0 * Ru ) )*/ f_flux = rb * C1 ; b_flux = ( 2.0 * Ru ) * C2 ; DC1 -= (f_flux - b_flux); DC2 += (f_flux - b_flux); /*REACTION*/ /* ~ C2 <-> D ( Rd , Rr )*/ f_flux = Rd * C2 ; b_flux = Rr * D ; DC2 -= (f_flux - b_flux); DD += (f_flux - b_flux); /*REACTION*/ /* ~ C2 <-> O ( Ro , Rc )*/ f_flux = Ro * C2 ; b_flux = Rc * O ; DC2 -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ O <-> OB ( RMgB , RMgU )*/ f_flux = RMgB * O ; b_flux = RMgU * OB ; DO -= (f_flux - b_flux); DOB += (f_flux - b_flux); /*REACTION*/ /* ~ OB <-> CB2 ( ( 3.0 * Rc ) , Ro )*/ f_flux = ( 3.0 * Rc ) * OB ; b_flux = Ro * CB2 ; DOB -= (f_flux - b_flux); DCB2 += (f_flux - b_flux); /*REACTION*/ /* ~ CB2 <-> DB ( Rd , Rr )*/ f_flux = Rd * CB2 ; b_flux = Rr * DB ; DCB2 -= (f_flux - b_flux); DDB += (f_flux - b_flux); /*REACTION*/ /* ~ CB2 <-> CB1 ( ( 2.0 * Ru ) , rb )*/ f_flux = ( 2.0 * Ru ) * CB2 ; b_flux = rb * CB1 ; DCB2 -= (f_flux - b_flux); DCB1 += (f_flux - b_flux); /*REACTION*/ /* ~ CB1 <-> CB0 ( Ru , ( 2.0 * rb ) )*/ f_flux = Ru * CB1 ; b_flux = ( 2.0 * rb ) * CB0 ; DCB1 -= (f_flux - b_flux); DCB0 += (f_flux - b_flux); /*REACTION*/ /* C0 + C1 + C2 + D + O + CB0 + CB1 + CB2 + DB + OB = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE matsol*/ static int _ode_matsol1(void* _so, double* _rhs, _threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; b_flux = f_flux = 0.; {int _i; double _dt1 = 1.0/dt; for(_i=0;_i<10;_i++){ _RHS1(_i) = _dt1*(_p[_dlist1[_i]]); _MATELM1(_i, _i) = _dt1; } } release ( _threadargscomma_ t ) ; rb = Rb * T ; rates ( _threadargscomma_ v ) ; /* ~ C0 <-> C1 ( ( 2.0 * rb ) , Ru )*/ _term = ( 2.0 * rb ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = Ru ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ C1 <-> C2 ( rb , ( 2.0 * Ru ) )*/ _term = rb ; _MATELM1( 5 ,5) += _term; _MATELM1( 4 ,5) -= _term; _term = ( 2.0 * Ru ) ; _MATELM1( 5 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ C2 <-> D ( Rd , Rr )*/ _term = Rd ; _MATELM1( 4 ,4) += _term; _MATELM1( 8 ,4) -= _term; _term = Rr ; _MATELM1( 4 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* ~ C2 <-> O ( Ro , Rc )*/ _term = Ro ; _MATELM1( 4 ,4) += _term; _MATELM1( 9 ,4) -= _term; _term = Rc ; _MATELM1( 4 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ O <-> OB ( RMgB , RMgU )*/ _term = RMgB ; _MATELM1( 9 ,9) += _term; _MATELM1( 0 ,9) -= _term; _term = RMgU ; _MATELM1( 9 ,0) -= _term; _MATELM1( 0 ,0) += _term; /*REACTION*/ /* ~ OB <-> CB2 ( ( 3.0 * Rc ) , Ro )*/ _term = ( 3.0 * Rc ) ; _MATELM1( 0 ,0) += _term; _MATELM1( 1 ,0) -= _term; _term = Ro ; _MATELM1( 0 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ CB2 <-> DB ( Rd , Rr )*/ _term = Rd ; _MATELM1( 1 ,1) += _term; _MATELM1( 7 ,1) -= _term; _term = Rr ; _MATELM1( 1 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ CB2 <-> CB1 ( ( 2.0 * Ru ) , rb )*/ _term = ( 2.0 * Ru ) ; _MATELM1( 1 ,1) += _term; _MATELM1( 2 ,1) -= _term; _term = rb ; _MATELM1( 1 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ CB1 <-> CB0 ( Ru , ( 2.0 * rb ) )*/ _term = Ru ; _MATELM1( 2 ,2) += _term; _MATELM1( 3 ,2) -= _term; _term = ( 2.0 * rb ) ; _MATELM1( 2 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* C0 + C1 + C2 + D + O + CB0 + CB1 + CB2 + DB + OB = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE end*/ static void _thread_cleanup(ThreadDatum* _thread) { _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_cvspth1]._pvoid); _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_spth1]._pvoid); } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ CB2 = CB20; CB1 = CB10; CB0 = CB00; C2 = C20; C1 = C10; C0 = C00; DB = DB0; D = D0; OB = OB0; O = O0; { T = 0.0 ; synon = 0.0 ; tRel = 0.0 ; rates ( _threadargscomma_ v ) ; C0 = 1.0 ; C1 = 0.0 ; C2 = 0.0 ; D = 0.0 ; O = 0.0 ; CB0 = 0.0 ; CB1 = 0.0 ; CB2 = 0.0 ; DB = 0.0 ; OB = 0.0 ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; if (!_thread[_spth1]._pvoid) { _thread[_spth1]._pvoid = nrn_cons_sparseobj(kstates_NMDA10_2{}, 10, _ml, _threadargs_); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_so = (void*) acc_deviceptr(_thread[_spth1]._pvoid); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[_spth1]._pvoid), &_d_so, sizeof(void*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _tsav = -1e20; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { g = w * gmax * O ; i = g * ( v - Erev ) ; } _current += i; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; double * _vec_shadow_rhs = _nt->_shadow_rhs; double * _vec_shadow_d = _nt->_shadow_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V _g = _nrn_current(_threadargs_, _v + .001); { _rhs = _nrn_current(_threadargs_, _v); } _g = (_g - _rhs)/.001; double _mfact = 1.e2/(_nd_area); _g *= _mfact; _rhs *= _mfact; _PRCELLSTATE_G #ifdef _OPENACC if(_nt->compute_gpu) { #pragma acc atomic update _vec_rhs[_nd_idx] -= _rhs; #pragma acc atomic update _vec_d[_nd_idx] += _g; } else { _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; } #else _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; #endif } #ifdef _OPENACC if(!(_nt->compute_gpu)) { for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; } #else for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; #endif } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { { sparse_thread(static_cast(_thread[_spth1]._pvoid), 10, _slist1, _dlist1, &t, dt, kstates_NMDA10_2{}, _linmat1, _threadargs_); }}} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*10); _dlist1 = (int*)malloc(sizeof(int)*10); _slist1[0] = &(OB) - _p; _dlist1[0] = &(DOB) - _p; _slist1[1] = &(CB2) - _p; _dlist1[1] = &(DCB2) - _p; _slist1[2] = &(CB1) - _p; _dlist1[2] = &(DCB1) - _p; _slist1[3] = &(CB0) - _p; _dlist1[3] = &(DCB0) - _p; _slist1[4] = &(C2) - _p; _dlist1[4] = &(DC2) - _p; _slist1[5] = &(C1) - _p; _dlist1[5] = &(DC1) - _p; _slist1[6] = &(C0) - _p; _dlist1[6] = &(DC0) - _p; _slist1[7] = &(DB) - _p; _dlist1[7] = &(DDB) - _p; _slist1[8] = &(D) - _p; _dlist1[8] = &(DD) - _p; _slist1[9] = &(O) - _p; _dlist1[9] = &(DO) - _p; #pragma acc enter data copyin(_slist1[0:10]) #pragma acc enter data copyin(_dlist1[0:10]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/SynNMDA10_2_2.cpp000066400000000000000000001016111425457616700231770ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:2] , _slist1[0:10], _dlist1[0:10] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #if !defined(NET_RECEIVE_BUFFERING) #define NET_RECEIVE_BUFFERING 1 #endif #define nrn_init _nrn_init__NMDA10_2_2 #define nrn_cur _nrn_cur__NMDA10_2_2 #define _nrn_current _nrn_current__NMDA10_2_2 #define nrn_jacob _nrn_jacob__NMDA10_2_2 #define nrn_state _nrn_state__NMDA10_2_2 #define initmodel initmodel__NMDA10_2_2 #define _net_receive _net_receive__NMDA10_2_2 #define _net_init _net_init__NMDA10_2_2 #define nrn_state_launcher nrn_state_NMDA10_2_2_launcher #define nrn_cur_launcher nrn_cur_NMDA10_2_2_launcher #define nrn_jacob_launcher nrn_jacob_NMDA10_2_2_launcher #if NET_RECEIVE_BUFFERING #define _net_buf_receive _net_buf_receive_NMDA10_2_2 void _net_buf_receive(NrnThread*); #endif #define kstates kstates_NMDA10_2_2 #define release release_NMDA10_2_2 #define rates rates_NMDA10_2_2 #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define Erev _p[0*_STRIDE] #define gmax _p[1*_STRIDE] #define Rb _p[2*_STRIDE] #define Ru _p[3*_STRIDE] #define Rd _p[4*_STRIDE] #define Rr _p[5*_STRIDE] #define Ro _p[6*_STRIDE] #define Rc _p[7*_STRIDE] #define tau _p[8*_STRIDE] #define T_max _p[9*_STRIDE] #define i _p[10*_STRIDE] #define g _p[11*_STRIDE] #define rb _p[12*_STRIDE] #define RMgB _p[13*_STRIDE] #define RMgU _p[14*_STRIDE] #define T _p[15*_STRIDE] #define tRel _p[16*_STRIDE] #define synon _p[17*_STRIDE] #define C0 _p[18*_STRIDE] #define C1 _p[19*_STRIDE] #define C2 _p[20*_STRIDE] #define D _p[21*_STRIDE] #define O _p[22*_STRIDE] #define CB0 _p[23*_STRIDE] #define CB1 _p[24*_STRIDE] #define CB2 _p[25*_STRIDE] #define DB _p[26*_STRIDE] #define OB _p[27*_STRIDE] #define w _p[28*_STRIDE] #define DC0 _p[29*_STRIDE] #define DC1 _p[30*_STRIDE] #define DC2 _p[31*_STRIDE] #define DD _p[32*_STRIDE] #define DO _p[33*_STRIDE] #define DCB0 _p[34*_STRIDE] #define DCB1 _p[35*_STRIDE] #define DCB2 _p[36*_STRIDE] #define DDB _p[37*_STRIDE] #define DOB _p[38*_STRIDE] #define _v_unused _p[39*_STRIDE] #define _g_unused _p[40*_STRIDE] #define _tsav _p[41*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _nd_area _nt_data[_ppvar[0*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static double _hoc_release(); static double _hoc_rates(); #endif /*BBCORE*/ #define _mechtype _mechtype_NMDA10_2_2 int _mechtype; #pragma acc declare copyin (_mechtype) static int _pointtype; #if 0 /*BBCORE*/ static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process(); return create_point_process(_pointtype, _ho); } static void _hoc_destroy_pnt(); static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process(); return loc_point_process(_pointtype, _vptr); } static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point(); return has_loc_point(_vptr); } static double _hoc_get_loc_pnt(_vptr)void* _vptr; { double get_loc_point_process(); return (get_loc_point_process(_vptr)); } #endif /*BBCORE*/ #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { 0,0 }; static Member_func _member_func[] = { "loc", _hoc_loc_pnt, "has_loc", _hoc_has_loc, "get_loc", _hoc_get_loc_pnt, "release", _hoc_release, "rates", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ #define mg mg_NMDA10_2_2 double mg = 1; #pragma acc declare copyin (mg) static void _acc_globals_update() { #pragma acc update device (mg) if(nrn_threads->compute_gpu) } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "tau", 1e-09, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "mg_NMDA10_2_2", "mM", "Erev", "mV", "gmax", "pS", "Rb", "/mM", "Ru", "/ms", "Rd", "/ms", "Rr", "/ms", "Ro", "/ms", "Rc", "/ms", "tau", "ms", "T_max", "mM", "i", "nA", "g", "uS", "rb", "/ms", "RMgB", "/ms", "RMgU", "/ms", "T", "mM", "tRel", "ms", 0,0 }; #endif /*BBCORE*/ static double CB20 = 0; #pragma acc declare copyin(CB20) static double CB10 = 0; #pragma acc declare copyin(CB10) static double CB00 = 0; #pragma acc declare copyin(CB00) static double C20 = 0; #pragma acc declare copyin(C20) static double C10 = 0; #pragma acc declare copyin(C10) static double C00 = 0; #pragma acc declare copyin(C00) static double DB0 = 0; #pragma acc declare copyin(DB0) static double D0 = 0; #pragma acc declare copyin(D0) static double OB0 = 0; #pragma acc declare copyin(OB0) static double O0 = 0; #pragma acc declare copyin(O0) static double delta_t = 1; #pragma acc declare copyin(delta_t) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "mg_NMDA10_2_2", &mg_NMDA10_2_2, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); #if 0 /*BBCORE*/ static void _hoc_destroy_pnt(_vptr) void* _vptr; { destroy_point_process(_vptr); } #endif /*BBCORE*/ /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NMDA10_2_2", "Erev", "gmax", "Rb", "Ru", "Rd", "Rr", "Ro", "Rc", "tau", "T_max", 0, "i", "g", "rb", "RMgB", "RMgU", "T", "tRel", "synon", 0, "C0", "C1", "C2", "D", "O", "CB0", "CB1", "CB2", "DB", "OB", 0, 0}; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ Erev = -0.7; gmax = 50; Rb = 2.83; Ru = 0.0381; Rd = 4.7161; Rr = 0.16116; Ro = 0.099631; Rc = 0.056999; tau = 0.3; T_max = 1.5; #endif /* BBCORE */ } static void _initlists(); #define _tqitem &(_nt->_vdata[_ppvar[2*_STRIDE]]) #if NET_RECEIVE_BUFFERING #undef _tqitem #define _tqitem _ppvar[2*_STRIDE] #endif void _net_receive(Point_process*, int, double); static void _thread_cleanup(ThreadDatum*); #define _psize 42 #define _ppsize 3 void _SynNMDA10_2_2_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); #if 0 /*BBCORE*/ #endif /*BBCORE*/ _pointtype = point_register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/ 3); _extcall_thread = (ThreadDatum*)ecalloc(2, sizeof(ThreadDatum)); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "area"); hoc_register_dparam_semantics(_mechtype, 1, "pntproc"); hoc_register_dparam_semantics(_mechtype, 2, "netsend"); #if NET_RECEIVE_BUFFERING hoc_register_net_receive_buffering(_net_buf_receive, _mechtype); #endif #if NET_RECEIVE_BUFFERING hoc_register_net_send_buffering(_mechtype); #endif set_pnt_receive(_mechtype, _net_receive, nullptr, 1); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "detailed model of glutamate NMDA receptors"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int release(_threadargsprotocomma_ double); static inline int rates(_threadargsprotocomma_ double); #define _MATELM1(_row,_col) _nrn_thread_getelm((SparseObj*)_so, _row + 1, _col + 1, _iml)[_iml] #define _RHS1(_arg) _rhs[(_arg+1)*_STRIDE] #define _linmat1 1 static int _spth1 = 1; static int _cvspth1 = 0; static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_NMDA10_2_2 int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NMDA10_2_2 int* _dlist1; #pragma acc declare create(_dlist1) /* _kinetic_ kstates _NMDA10_2_2 */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct kstates_NMDA10_2_2 { int operator()(SparseObj* _so, double* _rhs, _threadargsproto_) const; }; int kstates_NMDA10_2_2::operator() (SparseObj* _so, double* _rhs, _threadargsproto_) const {int _reset=0; { double b_flux, f_flux, _term; int _i; {int _i; double _dt1 = 1.0/dt; for(_i=1;_i<10;_i++){ _RHS1(_i) = -_dt1*(_p[_slist1[_i]*_STRIDE] - _p[_dlist1[_i]*_STRIDE]); _MATELM1(_i, _i) = _dt1; } } release ( _threadargscomma_ t ) ; rb = Rb * T ; rates ( _threadargscomma_ v ) ; /* ~ C0 <-> C1 ( ( 2.0 * rb ) , Ru )*/ f_flux = ( 2.0 * rb ) * C0 ; b_flux = Ru * C1 ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 5) += (f_flux - b_flux); _term = ( 2.0 * rb ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = Ru ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ C1 <-> C2 ( rb , ( 2.0 * Ru ) )*/ f_flux = rb * C1 ; b_flux = ( 2.0 * Ru ) * C2 ; _RHS1( 5) -= (f_flux - b_flux); _RHS1( 4) += (f_flux - b_flux); _term = rb ; _MATELM1( 5 ,5) += _term; _MATELM1( 4 ,5) -= _term; _term = ( 2.0 * Ru ) ; _MATELM1( 5 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ C2 <-> D ( Rd , Rr )*/ f_flux = Rd * C2 ; b_flux = Rr * D ; _RHS1( 4) -= (f_flux - b_flux); _RHS1( 8) += (f_flux - b_flux); _term = Rd ; _MATELM1( 4 ,4) += _term; _MATELM1( 8 ,4) -= _term; _term = Rr ; _MATELM1( 4 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* ~ C2 <-> O ( Ro , Rc )*/ f_flux = Ro * C2 ; b_flux = Rc * O ; _RHS1( 4) -= (f_flux - b_flux); _RHS1( 9) += (f_flux - b_flux); _term = Ro ; _MATELM1( 4 ,4) += _term; _MATELM1( 9 ,4) -= _term; _term = Rc ; _MATELM1( 4 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ O <-> OB ( RMgB , RMgU )*/ f_flux = RMgB * O ; b_flux = RMgU * OB ; _RHS1( 9) -= (f_flux - b_flux); _term = RMgB ; _MATELM1( 9 ,9) += _term; _term = RMgU ; _MATELM1( 9 ,0) -= _term; /*REACTION*/ /* ~ OB <-> CB2 ( ( 3.0 * Rc ) , Ro )*/ f_flux = ( 3.0 * Rc ) * OB ; b_flux = Ro * CB2 ; _RHS1( 1) += (f_flux - b_flux); _term = ( 3.0 * Rc ) ; _MATELM1( 1 ,0) -= _term; _term = Ro ; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ CB2 <-> DB ( Rd , Rr )*/ f_flux = Rd * CB2 ; b_flux = Rr * DB ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 7) += (f_flux - b_flux); _term = Rd ; _MATELM1( 1 ,1) += _term; _MATELM1( 7 ,1) -= _term; _term = Rr ; _MATELM1( 1 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ CB2 <-> CB1 ( ( 2.0 * Ru ) , rb )*/ f_flux = ( 2.0 * Ru ) * CB2 ; b_flux = rb * CB1 ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = ( 2.0 * Ru ) ; _MATELM1( 1 ,1) += _term; _MATELM1( 2 ,1) -= _term; _term = rb ; _MATELM1( 1 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ CB1 <-> CB0 ( Ru , ( 2.0 * rb ) )*/ f_flux = Ru * CB1 ; b_flux = ( 2.0 * rb ) * CB0 ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 3) += (f_flux - b_flux); _term = Ru ; _MATELM1( 2 ,2) += _term; _MATELM1( 3 ,2) -= _term; _term = ( 2.0 * rb ) ; _MATELM1( 2 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* C0 + C1 + C2 + D + O + CB0 + CB1 + CB2 + DB + OB = 1.0 */ _RHS1(0) = 1.0; _MATELM1(0, 0) = 1; _RHS1(0) -= OB ; _MATELM1(0, 7) = 1; _RHS1(0) -= DB ; _MATELM1(0, 1) = 1; _RHS1(0) -= CB2 ; _MATELM1(0, 2) = 1; _RHS1(0) -= CB1 ; _MATELM1(0, 3) = 1; _RHS1(0) -= CB0 ; _MATELM1(0, 9) = 1; _RHS1(0) -= O ; _MATELM1(0, 8) = 1; _RHS1(0) -= D ; _MATELM1(0, 4) = 1; _RHS1(0) -= C2 ; _MATELM1(0, 5) = 1; _RHS1(0) -= C1 ; _MATELM1(0, 6) = 1; _RHS1(0) -= C0 ; /*CONSERVATION*/ } return _reset; } #if NET_RECEIVE_BUFFERING #undef t #define t _nrb_t static inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag); void _net_buf_receive(NrnThread* _nt) { if (!_nt->_ml_list) { return; } Memb_list* _ml = _nt->_ml_list[_mechtype]; if (!_ml) { return; } NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer; int _di; int stream_id = _nt->stream_id; Point_process* _pnt = _nt->pntprocs; int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset; int _displ_cnt = _nrb->_displ_cnt; _PRAGMA_FOR_NETRECV_ACC_LOOP_ for (_di = 0; _di < _displ_cnt; ++_di) { int _inrb; int _di0 = _nrb->_displ[_di]; int _di1 = _nrb->_displ[_di + 1]; for (_inrb = _di0; _inrb < _di1; ++_inrb) { int _i = _nrb->_nrb_index[_inrb]; int _j = _nrb->_pnt_index[_i]; int _k = _nrb->_weight_index[_i]; double _nrt = _nrb->_nrb_t[_i]; double _nrflag = _nrb->_nrb_flag[_i]; _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag); } } #pragma acc wait(stream_id) _nrb->_displ_cnt = 0; _nrb->_cnt = 0; /*printf("_net_buf_receive__NMDA10_2_2 %d\n", _nt->_id);*/ { NetSendBuffer_t* _nsb = _ml->_net_send_buffer; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu) update_net_send_buffer_on_host(_nt, _nsb); #endif int _i; for (_i=0; _i < _nsb->_cnt; ++_i) { net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i], _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i], _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]); } _nsb->_cnt = 0; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update device(_nsb->_cnt) if (_nt->compute_gpu) #endif } } static void _net_send_buffering(NetSendBuffer_t* _nsb, int _sendtype, int _i_vdata, int _weight_index, int _ipnt, double _t, double _flag) { int _i = 0; #pragma acc atomic capture _i = _nsb->_cnt++; #if !defined(_OPENACC) if (_i >= _nsb->_size) { _nsb->grow(); } #endif if (_i < _nsb->_size) { _nsb->_sendtype[_i] = _sendtype; _nsb->_vdata_index[_i] = _i_vdata; _nsb->_weight_index[_i] = _weight_index; _nsb->_pnt_index[_i] = _ipnt; _nsb->_nsb_t[_i] = _t; _nsb->_nsb_flag[_i] = _flag; } } void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) { NrnThread* _nt = nrn_threads + _pnt->_tid; NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer; if (_nrb->_cnt >= _nrb->_size){ realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]); } _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs; _nrb->_weight_index[_nrb->_cnt] = _weight_index; _nrb->_nrb_t[_nrb->_cnt] = _nt->_t; _nrb->_nrb_flag[_nrb->_cnt] = _lflag; ++_nrb->_cnt; } static void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag) #else void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) #endif { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0; Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args; NrnThread* _nt; int _tid = _pnt->_tid; _nt = nrn_threads + _tid; _thread = (ThreadDatum*)0; double *_weights = _nt->_weights; _args = _weights + _weight_index; _ml = _nt->_ml_list[_pnt->_type]; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _iml = _pnt->_i_instance; #if LAYOUT == 1 /*AoS*/ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #endif #if LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; #endif #if LAYOUT > 1 /*AoSoA*/ #error AoSoA not implemented. #endif #if !defined(_OPENACC) assert(_tsav <= t); #endif _tsav = t; #if !NET_RECEIVE_BUFFERING if (_lflag == 1. ) {*(_tqitem) = 0;} #endif { if ( _lflag == 0.0 ) { tRel = t ; synon = 1.0 ; w = _args[0] ; } if ( _lflag == 1.0 ) { C0 = 1.0 ; C1 = 0.0 ; C2 = 0.0 ; D = 0.0 ; O = 0.0 ; CB0 = 0.0 ; CB1 = 0.0 ; CB2 = 0.0 ; DB = 0.0 ; OB = 0.0 ; } } #if NET_RECEIVE_BUFFERING #undef t #define t _nt->_t #endif } static int release ( _threadargsprotocomma_ double _lt ) { T = T_max * ( _lt - tRel ) / tau * exp ( 1.0 - ( _lt - tRel ) / tau ) * synon ; return 0; } #if 0 /*BBCORE*/ static double _hoc_release(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; release ( _threadargs_, *getarg(1) ); return(_r); } #endif /*BBCORE*/ static int rates ( _threadargsprotocomma_ double _lv ) { RMgB = 610e-3 * exp ( 1.0 * - _lv / 17.0 ) * ( mg / 1.0 ) * 1.0 ; RMgU = 5400e-3 * exp ( 1.0 * _lv / 47.0 ) * 1.0 ; return 0; } #if 0 /*BBCORE*/ static double _hoc_rates(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; rates ( _threadargs_, *getarg(1) ); return(_r); } #endif /*BBCORE*/ /*CVODE ode begin*/ static int _ode_spec1(_threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; {int _i; for(_i=0;_i<10;_i++) _p[_dlist1[_i]] = 0.0;} release ( _threadargscomma_ t ) ; rb = Rb * T ; rates ( _threadargscomma_ v ) ; /* ~ C0 <-> C1 ( ( 2.0 * rb ) , Ru )*/ f_flux = ( 2.0 * rb ) * C0 ; b_flux = Ru * C1 ; DC0 -= (f_flux - b_flux); DC1 += (f_flux - b_flux); /*REACTION*/ /* ~ C1 <-> C2 ( rb , ( 2.0 * Ru ) )*/ f_flux = rb * C1 ; b_flux = ( 2.0 * Ru ) * C2 ; DC1 -= (f_flux - b_flux); DC2 += (f_flux - b_flux); /*REACTION*/ /* ~ C2 <-> D ( Rd , Rr )*/ f_flux = Rd * C2 ; b_flux = Rr * D ; DC2 -= (f_flux - b_flux); DD += (f_flux - b_flux); /*REACTION*/ /* ~ C2 <-> O ( Ro , Rc )*/ f_flux = Ro * C2 ; b_flux = Rc * O ; DC2 -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ O <-> OB ( RMgB , RMgU )*/ f_flux = RMgB * O ; b_flux = RMgU * OB ; DO -= (f_flux - b_flux); DOB += (f_flux - b_flux); /*REACTION*/ /* ~ OB <-> CB2 ( ( 3.0 * Rc ) , Ro )*/ f_flux = ( 3.0 * Rc ) * OB ; b_flux = Ro * CB2 ; DOB -= (f_flux - b_flux); DCB2 += (f_flux - b_flux); /*REACTION*/ /* ~ CB2 <-> DB ( Rd , Rr )*/ f_flux = Rd * CB2 ; b_flux = Rr * DB ; DCB2 -= (f_flux - b_flux); DDB += (f_flux - b_flux); /*REACTION*/ /* ~ CB2 <-> CB1 ( ( 2.0 * Ru ) , rb )*/ f_flux = ( 2.0 * Ru ) * CB2 ; b_flux = rb * CB1 ; DCB2 -= (f_flux - b_flux); DCB1 += (f_flux - b_flux); /*REACTION*/ /* ~ CB1 <-> CB0 ( Ru , ( 2.0 * rb ) )*/ f_flux = Ru * CB1 ; b_flux = ( 2.0 * rb ) * CB0 ; DCB1 -= (f_flux - b_flux); DCB0 += (f_flux - b_flux); /*REACTION*/ /* C0 + C1 + C2 + D + O + CB0 + CB1 + CB2 + DB + OB = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE matsol*/ static int _ode_matsol1(void* _so, double* _rhs, _threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; b_flux = f_flux = 0.; {int _i; double _dt1 = 1.0/dt; for(_i=0;_i<10;_i++){ _RHS1(_i) = _dt1*(_p[_dlist1[_i]]); _MATELM1(_i, _i) = _dt1; } } release ( _threadargscomma_ t ) ; rb = Rb * T ; rates ( _threadargscomma_ v ) ; /* ~ C0 <-> C1 ( ( 2.0 * rb ) , Ru )*/ _term = ( 2.0 * rb ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = Ru ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ C1 <-> C2 ( rb , ( 2.0 * Ru ) )*/ _term = rb ; _MATELM1( 5 ,5) += _term; _MATELM1( 4 ,5) -= _term; _term = ( 2.0 * Ru ) ; _MATELM1( 5 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ C2 <-> D ( Rd , Rr )*/ _term = Rd ; _MATELM1( 4 ,4) += _term; _MATELM1( 8 ,4) -= _term; _term = Rr ; _MATELM1( 4 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* ~ C2 <-> O ( Ro , Rc )*/ _term = Ro ; _MATELM1( 4 ,4) += _term; _MATELM1( 9 ,4) -= _term; _term = Rc ; _MATELM1( 4 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ O <-> OB ( RMgB , RMgU )*/ _term = RMgB ; _MATELM1( 9 ,9) += _term; _MATELM1( 0 ,9) -= _term; _term = RMgU ; _MATELM1( 9 ,0) -= _term; _MATELM1( 0 ,0) += _term; /*REACTION*/ /* ~ OB <-> CB2 ( ( 3.0 * Rc ) , Ro )*/ _term = ( 3.0 * Rc ) ; _MATELM1( 0 ,0) += _term; _MATELM1( 1 ,0) -= _term; _term = Ro ; _MATELM1( 0 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ CB2 <-> DB ( Rd , Rr )*/ _term = Rd ; _MATELM1( 1 ,1) += _term; _MATELM1( 7 ,1) -= _term; _term = Rr ; _MATELM1( 1 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ CB2 <-> CB1 ( ( 2.0 * Ru ) , rb )*/ _term = ( 2.0 * Ru ) ; _MATELM1( 1 ,1) += _term; _MATELM1( 2 ,1) -= _term; _term = rb ; _MATELM1( 1 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ CB1 <-> CB0 ( Ru , ( 2.0 * rb ) )*/ _term = Ru ; _MATELM1( 2 ,2) += _term; _MATELM1( 3 ,2) -= _term; _term = ( 2.0 * rb ) ; _MATELM1( 2 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* C0 + C1 + C2 + D + O + CB0 + CB1 + CB2 + DB + OB = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE end*/ static void _thread_cleanup(ThreadDatum* _thread) { _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_cvspth1]._pvoid); _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_spth1]._pvoid); } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ Memb_list* _ml = _nt->_ml_list[_mechtype]; CB2 = CB20; CB1 = CB10; CB0 = CB00; C2 = C20; C1 = C10; C0 = C00; DB = DB0; D = D0; OB = OB0; O = O0; { T = 0.0 ; synon = 0.0 ; tRel = 0.0 ; rates ( _threadargscomma_ v ) ; C0 = 1.0 ; C1 = 0.0 ; C2 = 0.0 ; D = 0.0 ; O = 0.0 ; CB0 = 0.0 ; CB1 = 0.0 ; CB2 = 0.0 ; DB = 0.0 ; OB = 0.0 ; #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, 0, _ppvar[1*_STRIDE], t + 590.0 , 1.0 ); #else net_send ( _tqitem, -1, (Point_process*) _nt->_vdata[_ppvar[1*_STRIDE]], t + 590.0 , 1.0 ) ; #endif } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #pragma acc update device (_mechtype) if(_nt->compute_gpu) if (!_thread[_spth1]._pvoid) { _thread[_spth1]._pvoid = nrn_cons_sparseobj(kstates_NMDA10_2_2{}, 10, _ml, _threadargs_); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_so = (void*) acc_deviceptr(_thread[_spth1]._pvoid); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[_spth1]._pvoid), &_d_so, sizeof(void*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _tsav = -1e20; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V initmodel(_threadargs_); } } #if NET_RECEIVE_BUFFERING NetSendBuffer_t* _nsb = _ml->_net_send_buffer; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc wait(stream_id) #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu) update_net_send_buffer_on_host(_nt, _nsb); #endif {int _i; for (_i=0; _i < _nsb->_cnt; ++_i) { net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i], _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i], _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]); }} _nsb->_cnt = 0; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update device(_nsb->_cnt) if(_nt->compute_gpu) #endif #endif } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { g = w * gmax * O ; i = g * ( v - Erev ) ; } _current += i; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; double * _vec_shadow_rhs = _nt->_shadow_rhs; double * _vec_shadow_d = _nt->_shadow_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V _g = _nrn_current(_threadargs_, _v + .001); { _rhs = _nrn_current(_threadargs_, _v); } _g = (_g - _rhs)/.001; double _mfact = 1.e2/(_nd_area); _g *= _mfact; _rhs *= _mfact; _PRCELLSTATE_G #ifdef _OPENACC if(_nt->compute_gpu) { #pragma acc atomic update _vec_rhs[_nd_idx] -= _rhs; #pragma acc atomic update _vec_d[_nd_idx] += _g; } else { _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; } #else _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; #endif } #ifdef _OPENACC if(!(_nt->compute_gpu)) { for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; } #else for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; #endif } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { { sparse_thread(static_cast(_thread[_spth1]._pvoid), 10, _slist1, _dlist1, &t, dt, kstates_NMDA10_2_2{}, _linmat1, _threadargs_); }}} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*10); _dlist1 = (int*)malloc(sizeof(int)*10); _slist1[0] = &(OB) - _p; _dlist1[0] = &(DOB) - _p; _slist1[1] = &(CB2) - _p; _dlist1[1] = &(DCB2) - _p; _slist1[2] = &(CB1) - _p; _dlist1[2] = &(DCB1) - _p; _slist1[3] = &(CB0) - _p; _dlist1[3] = &(DCB0) - _p; _slist1[4] = &(C2) - _p; _dlist1[4] = &(DC2) - _p; _slist1[5] = &(C1) - _p; _dlist1[5] = &(DC1) - _p; _slist1[6] = &(C0) - _p; _dlist1[6] = &(DC0) - _p; _slist1[7] = &(DB) - _p; _dlist1[7] = &(DDB) - _p; _slist1[8] = &(D) - _p; _dlist1[8] = &(DD) - _p; _slist1[9] = &(O) - _p; _dlist1[9] = &(DO) - _p; #pragma acc enter data copyin(_slist1[0:10]) #pragma acc enter data copyin(_dlist1[0:10]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/SynNMDA16.cpp000066400000000000000000001251101425457616700225430ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:3] , _slist1[0:16], _dlist1[0:16] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #if !defined(NET_RECEIVE_BUFFERING) #define NET_RECEIVE_BUFFERING 1 #endif #define nrn_init _nrn_init__NMDA16 #define nrn_cur _nrn_cur__NMDA16 #define _nrn_current _nrn_current__NMDA16 #define nrn_jacob _nrn_jacob__NMDA16 #define nrn_state _nrn_state__NMDA16 #define initmodel initmodel__NMDA16 #define _net_receive _net_receive__NMDA16 #define _net_init _net_init__NMDA16 #define nrn_state_launcher nrn_state_NMDA16_launcher #define nrn_cur_launcher nrn_cur_NMDA16_launcher #define nrn_jacob_launcher nrn_jacob_NMDA16_launcher #if NET_RECEIVE_BUFFERING #define _net_buf_receive _net_buf_receive_NMDA16 void _net_buf_receive(NrnThread*); #endif #define kstates kstates_NMDA16 #define rates rates_NMDA16 #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define Erev _p[0*_STRIDE] #define tau _p[1*_STRIDE] #define T_max _p[2*_STRIDE] #define kd1F _p[3*_STRIDE] #define kd1B _p[4*_STRIDE] #define kd2F _p[5*_STRIDE] #define kd2B _p[6*_STRIDE] #define csi _p[7*_STRIDE] #define i _p[8*_STRIDE] #define g _p[9*_STRIDE] #define T _p[10*_STRIDE] #define tRel _p[11*_STRIDE] #define synon _p[12*_STRIDE] #define R _p[13*_STRIDE] #define RA _p[14*_STRIDE] #define RA2 _p[15*_STRIDE] #define RA2d1 _p[16*_STRIDE] #define RA2d2 _p[17*_STRIDE] #define RA2f _p[18*_STRIDE] #define RA2s _p[19*_STRIDE] #define O _p[20*_STRIDE] #define OMg _p[21*_STRIDE] #define RMg _p[22*_STRIDE] #define RAMg _p[23*_STRIDE] #define RA2Mg _p[24*_STRIDE] #define RA2d1Mg _p[25*_STRIDE] #define RA2d2Mg _p[26*_STRIDE] #define RA2fMg _p[27*_STRIDE] #define RA2sMg _p[28*_STRIDE] #define w _p[29*_STRIDE] #define nao _p[30*_STRIDE] #define DR _p[31*_STRIDE] #define DRA _p[32*_STRIDE] #define DRA2 _p[33*_STRIDE] #define DRA2d1 _p[34*_STRIDE] #define DRA2d2 _p[35*_STRIDE] #define DRA2f _p[36*_STRIDE] #define DRA2s _p[37*_STRIDE] #define DO _p[38*_STRIDE] #define DOMg _p[39*_STRIDE] #define DRMg _p[40*_STRIDE] #define DRAMg _p[41*_STRIDE] #define DRA2Mg _p[42*_STRIDE] #define DRA2d1Mg _p[43*_STRIDE] #define DRA2d2Mg _p[44*_STRIDE] #define DRA2fMg _p[45*_STRIDE] #define DRA2sMg _p[46*_STRIDE] #define _v_unused _p[47*_STRIDE] #define _g_unused _p[48*_STRIDE] #define _tsav _p[49*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _nd_area _nt_data[_ppvar[0*_STRIDE]] #define _ion_nao _nt_data[_ppvar[2*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static double _hoc_rates(); #endif /*BBCORE*/ static int _mechtype; static int _pointtype; #if 0 /*BBCORE*/ static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process(); return create_point_process(_pointtype, _ho); } static void _hoc_destroy_pnt(); static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process(); return loc_point_process(_pointtype, _vptr); } static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point(); return has_loc_point(_vptr); } static double _hoc_get_loc_pnt(_vptr)void* _vptr; { double get_loc_point_process(); return (get_loc_point_process(_vptr)); } #endif /*BBCORE*/ #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { 0,0 }; static Member_func _member_func[] = { "loc", _hoc_loc_pnt, "has_loc", _hoc_has_loc, "get_loc", _hoc_get_loc_pnt, "rates", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ static int _thread1data_inuse = 0; static double _thread1data[10]; #define _gth 2 #define Kcs0 Kcs0_NMDA16 double Kcs0 = 0.27; #pragma acc declare copyin (Kcs0) #define Kna Kna_NMDA16 double Kna = 34.4; #pragma acc declare copyin (Kna) #define Kcs_NMDA16 _thread1data[0] #define Kcs _thread[_gth]._pval[0] #define Mg Mg_NMDA16 double Mg = 1; #pragma acc declare copyin (Mg) #define V0 V0_NMDA16 double V0 = -100; #pragma acc declare copyin (V0) #define Vdep Vdep_NMDA16 double Vdep = 175; #pragma acc declare copyin (Vdep) #define a a_NMDA16 double a = -21; #pragma acc declare copyin (a) #define b b_NMDA16 double b = -55; #pragma acc declare copyin (b) #define c c_NMDA16 double c = 52.7; #pragma acc declare copyin (c) #define d d_NMDA16 double d = -50; #pragma acc declare copyin (d) #define gmax gmax_NMDA16 double gmax = 50; #pragma acc declare copyin (gmax) #define kNi0 kNi0_NMDA16 double kNi0 = 0.0618; #pragma acc declare copyin (kNi0) #define kNo0 kNo0_NMDA16 double kNo0 = 110; #pragma acc declare copyin (kNo0) #define kP0 kP0_NMDA16 double kP0 = 1100; #pragma acc declare copyin (kP0) #define kfB0 kfB0_NMDA16 double kfB0 = 0.175; #pragma acc declare copyin (kfB0) #define kfF0 kfF0_NMDA16 double kfF0 = 2.836; #pragma acc declare copyin (kfF0) #define ksB0 ksB0_NMDA16 double ksB0 = 0.23; #pragma acc declare copyin (ksB0) #define ksF0 ksF0_NMDA16 double ksF0 = 0.048; #pragma acc declare copyin (ksF0) #define koff koff_NMDA16 double koff = 0.0381; #pragma acc declare copyin (koff) #define kon kon_NMDA16 double kon = 2.83; #pragma acc declare copyin (kon) #define kfB_NMDA16 _thread1data[1] #define kfB _thread[_gth]._pval[1] #define kfF_NMDA16 _thread1data[2] #define kfF _thread[_gth]._pval[2] #define ksB_NMDA16 _thread1data[3] #define ksB _thread[_gth]._pval[3] #define ksF_NMDA16 _thread1data[4] #define ksF _thread[_gth]._pval[4] #define kMgB_NMDA16 _thread1data[5] #define kMgB _thread[_gth]._pval[5] #define kMgF_NMDA16 _thread1data[6] #define kMgF _thread[_gth]._pval[6] #define kNi_NMDA16 _thread1data[7] #define kNi _thread[_gth]._pval[7] #define kNo_NMDA16 _thread1data[8] #define kNo _thread[_gth]._pval[8] #define kP_NMDA16 _thread1data[9] #define kP _thread[_gth]._pval[9] static void _acc_globals_update() { #pragma acc update device (Kcs0) if(nrn_threads->compute_gpu) #pragma acc update device (Kna) if(nrn_threads->compute_gpu) #pragma acc update device (Mg) if(nrn_threads->compute_gpu) #pragma acc update device (V0) if(nrn_threads->compute_gpu) #pragma acc update device (Vdep) if(nrn_threads->compute_gpu) #pragma acc update device (a) if(nrn_threads->compute_gpu) #pragma acc update device (b) if(nrn_threads->compute_gpu) #pragma acc update device (c) if(nrn_threads->compute_gpu) #pragma acc update device (d) if(nrn_threads->compute_gpu) #pragma acc update device (gmax) if(nrn_threads->compute_gpu) #pragma acc update device (kNi0) if(nrn_threads->compute_gpu) #pragma acc update device (kNo0) if(nrn_threads->compute_gpu) #pragma acc update device (kP0) if(nrn_threads->compute_gpu) #pragma acc update device (kfB0) if(nrn_threads->compute_gpu) #pragma acc update device (kfF0) if(nrn_threads->compute_gpu) #pragma acc update device (ksB0) if(nrn_threads->compute_gpu) #pragma acc update device (ksF0) if(nrn_threads->compute_gpu) #pragma acc update device (koff) if(nrn_threads->compute_gpu) #pragma acc update device (kon) if(nrn_threads->compute_gpu) } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "tau", 1e-09, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "gmax_NMDA16", "pS", "Mg_NMDA16", "mM", "kon_NMDA16", "/ms", "koff_NMDA16", "/ms", "ksF0_NMDA16", "/ms", "ksB0_NMDA16", "/ms", "kfF0_NMDA16", "/ms", "kfB0_NMDA16", "/ms", "Vdep_NMDA16", "mV", "V0_NMDA16", "mV", "Kna_NMDA16", "mM", "Kcs0_NMDA16", "mM", "a_NMDA16", "mV", "kP0_NMDA16", "/ms", "b_NMDA16", "mV", "kNo0_NMDA16", "/ms", "c_NMDA16", "mV", "kNi0_NMDA16", "/ms", "d_NMDA16", "mV", "ksF_NMDA16", "/ms", "ksB_NMDA16", "/ms", "kfF_NMDA16", "/ms", "kfB_NMDA16", "/ms", "kMgF_NMDA16", "/ms /mM", "kMgB_NMDA16", "/ms", "Kcs_NMDA16", "mM", "kP_NMDA16", "/ms /mM", "kNo_NMDA16", "/ms", "kNi_NMDA16", "/ms", "Erev", "mV", "tau", "ms", "T_max", "mM", "kd1F", "/ms", "kd1B", "/ms", "kd2F", "/ms", "kd2B", "/ms", "csi", "mM", "i", "nA", "g", "uS", "T", "mM", "tRel", "ms", 0,0 }; #endif /*BBCORE*/ static double OMg0 = 0; #pragma acc declare copyin(OMg0) static double O0 = 0; #pragma acc declare copyin(O0) static double RA2sMg0 = 0; #pragma acc declare copyin(RA2sMg0) static double RA2fMg0 = 0; #pragma acc declare copyin(RA2fMg0) static double RA2d2Mg0 = 0; #pragma acc declare copyin(RA2d2Mg0) static double RA2d1Mg0 = 0; #pragma acc declare copyin(RA2d1Mg0) static double RA2Mg0 = 0; #pragma acc declare copyin(RA2Mg0) static double RAMg0 = 0; #pragma acc declare copyin(RAMg0) static double RMg0 = 0; #pragma acc declare copyin(RMg0) static double RA2s0 = 0; #pragma acc declare copyin(RA2s0) static double RA2f0 = 0; #pragma acc declare copyin(RA2f0) static double RA2d20 = 0; #pragma acc declare copyin(RA2d20) static double RA2d10 = 0; #pragma acc declare copyin(RA2d10) static double RA20 = 0; #pragma acc declare copyin(RA20) static double RA0 = 0; #pragma acc declare copyin(RA0) static double R0 = 0; #pragma acc declare copyin(R0) static double delta_t = 1; #pragma acc declare copyin(delta_t) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "gmax_NMDA16", &gmax_NMDA16, "Mg_NMDA16", &Mg_NMDA16, "kon_NMDA16", &kon_NMDA16, "koff_NMDA16", &koff_NMDA16, "ksF0_NMDA16", &ksF0_NMDA16, "ksB0_NMDA16", &ksB0_NMDA16, "kfF0_NMDA16", &kfF0_NMDA16, "kfB0_NMDA16", &kfB0_NMDA16, "Vdep_NMDA16", &Vdep_NMDA16, "V0_NMDA16", &V0_NMDA16, "Kna_NMDA16", &Kna_NMDA16, "Kcs0_NMDA16", &Kcs0_NMDA16, "a_NMDA16", &a_NMDA16, "kP0_NMDA16", &kP0_NMDA16, "b_NMDA16", &b_NMDA16, "kNo0_NMDA16", &kNo0_NMDA16, "c_NMDA16", &c_NMDA16, "kNi0_NMDA16", &kNi0_NMDA16, "d_NMDA16", &d_NMDA16, "ksF_NMDA16", &ksF_NMDA16, "ksB_NMDA16", &ksB_NMDA16, "kfF_NMDA16", &kfF_NMDA16, "kfB_NMDA16", &kfB_NMDA16, "kMgF_NMDA16", &kMgF_NMDA16, "kMgB_NMDA16", &kMgB_NMDA16, "Kcs_NMDA16", &Kcs_NMDA16, "kP_NMDA16", &kP_NMDA16, "kNo_NMDA16", &kNo_NMDA16, "kNi_NMDA16", &kNi_NMDA16, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); #if 0 /*BBCORE*/ static void _hoc_destroy_pnt(_vptr) void* _vptr; { destroy_point_process(_vptr); } #endif /*BBCORE*/ /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NMDA16", "Erev", "tau", "T_max", "kd1F", "kd1B", "kd2F", "kd2B", "csi", 0, "i", "g", "T", "tRel", "synon", 0, "R", "RA", "RA2", "RA2d1", "RA2d2", "RA2f", "RA2s", "O", "OMg", "RMg", "RAMg", "RA2Mg", "RA2d1Mg", "RA2d2Mg", "RA2fMg", "RA2sMg", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ Erev = 0; tau = 0.3; T_max = 1.5; kd1F = 0.001; kd1B = 0.001; kd2F = 0.001; kd2B = 0.001; csi = 148; prop_ion = need_memb(_na_sym); nrn_promote(prop_ion, 1, 0); _ppvar[2]._pval = &prop_ion->param[2]; /* nao */ #endif /* BBCORE */ } static void _initlists(); void _net_receive(Point_process*, int, double); static void _thread_mem_init(ThreadDatum*); static void _thread_cleanup(ThreadDatum*); static void _update_ion_pointer(Datum*); #define _psize 50 #define _ppsize 3 void _SynNMDA16_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ _pointtype = point_register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/ 4); _extcall_thread = (ThreadDatum*)ecalloc(3, sizeof(ThreadDatum)); _thread_mem_init(_extcall_thread); _thread1data_inuse = 0; _nrn_thread_reg1(_mechtype, _thread_mem_init); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "area"); hoc_register_dparam_semantics(_mechtype, 1, "pntproc"); hoc_register_dparam_semantics(_mechtype, 2, "na_ion"); #if NET_RECEIVE_BUFFERING hoc_register_net_receive_buffering(_net_buf_receive, _mechtype); #endif set_pnt_receive(_mechtype, _net_receive, nullptr, 1); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "Voltage-dependent kinetic model of NMDA receptor"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int rates(_threadargsprotocomma_ double, double); #define _MATELM1(_row,_col) _nrn_thread_getelm((SparseObj*)_so, _row + 1, _col + 1, _iml)[_iml] #define _RHS1(_arg) _rhs[(_arg+1)*_STRIDE] #define _linmat1 1 static int _spth1 = 1; static int _cvspth1 = 0; static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_NMDA16 int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NMDA16 int* _dlist1; #pragma acc declare create(_dlist1) /* _kinetic_ kstates _NMDA16 */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct kstates_NMDA16 { int operator()(SparseObj* _so, double* _rhs, _threadargsproto_) const; }; int kstates_NMDA16::operator() (SparseObj* _so, double* _rhs, _threadargsproto_) const {int _reset=0; { double b_flux, f_flux, _term; int _i; {int _i; double _dt1 = 1.0/dt; for(_i=1;_i<16;_i++){ _RHS1(_i) = -_dt1*(_p[_slist1[_i]*_STRIDE] - _p[_dlist1[_i]*_STRIDE]); _MATELM1(_i, _i) = _dt1; } } rates ( _threadargscomma_ v , t ) ; /* ~ R <-> RA ( ( 2.0 * kon * T ) , koff )*/ f_flux = ( 2.0 * kon * T ) * R ; b_flux = koff * RA ; _RHS1( 15) -= (f_flux - b_flux); _RHS1( 14) += (f_flux - b_flux); _term = ( 2.0 * kon * T ) ; _MATELM1( 15 ,15) += _term; _MATELM1( 14 ,15) -= _term; _term = koff ; _MATELM1( 15 ,14) -= _term; _MATELM1( 14 ,14) += _term; /*REACTION*/ /* ~ RA <-> RA2 ( ( kon * T ) , ( 2.0 * koff ) )*/ f_flux = ( kon * T ) * RA ; b_flux = ( 2.0 * koff ) * RA2 ; _RHS1( 14) -= (f_flux - b_flux); _RHS1( 13) += (f_flux - b_flux); _term = ( kon * T ) ; _MATELM1( 14 ,14) += _term; _MATELM1( 13 ,14) -= _term; _term = ( 2.0 * koff ) ; _MATELM1( 14 ,13) -= _term; _MATELM1( 13 ,13) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d1 ( kd1F , kd1B )*/ f_flux = kd1F * RA2 ; b_flux = kd1B * RA2d1 ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 12) += (f_flux - b_flux); _term = kd1F ; _MATELM1( 13 ,13) += _term; _MATELM1( 12 ,13) -= _term; _term = kd1B ; _MATELM1( 13 ,12) -= _term; _MATELM1( 12 ,12) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d2 ( kd2F , kd2B )*/ f_flux = kd2F * RA2 ; b_flux = kd2B * RA2d2 ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 11) += (f_flux - b_flux); _term = kd2F ; _MATELM1( 13 ,13) += _term; _MATELM1( 11 ,13) -= _term; _term = kd2B ; _MATELM1( 13 ,11) -= _term; _MATELM1( 11 ,11) += _term; /*REACTION*/ /* ~ RA2 <-> RA2f ( kfF , kfB )*/ f_flux = kfF * RA2 ; b_flux = kfB * RA2f ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 10) += (f_flux - b_flux); _term = kfF ; _MATELM1( 13 ,13) += _term; _MATELM1( 10 ,13) -= _term; _term = kfB ; _MATELM1( 13 ,10) -= _term; _MATELM1( 10 ,10) += _term; /*REACTION*/ /* ~ RA2 <-> RA2s ( ksF , ksB )*/ f_flux = ksF * RA2 ; b_flux = ksB * RA2s ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 9) += (f_flux - b_flux); _term = ksF ; _MATELM1( 13 ,13) += _term; _MATELM1( 9 ,13) -= _term; _term = ksB ; _MATELM1( 13 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ RA2f <-> O ( ksF , ksB )*/ f_flux = ksF * RA2f ; b_flux = ksB * O ; _RHS1( 10) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = ksF ; _MATELM1( 10 ,10) += _term; _MATELM1( 2 ,10) -= _term; _term = ksB ; _MATELM1( 10 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ RA2s <-> O ( kfF , kfB )*/ f_flux = kfF * RA2s ; b_flux = kfB * O ; _RHS1( 9) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = kfF ; _MATELM1( 9 ,9) += _term; _MATELM1( 2 ,9) -= _term; _term = kfB ; _MATELM1( 9 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ O <-> OMg ( ( kMgF * Mg ) , kMgB )*/ f_flux = ( kMgF * Mg ) * O ; b_flux = kMgB * OMg ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 1) += (f_flux - b_flux); _term = ( kMgF * Mg ) ; _MATELM1( 2 ,2) += _term; _MATELM1( 1 ,2) -= _term; _term = kMgB ; _MATELM1( 2 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ OMg <-> RA2fMg ( ksB , ksF )*/ f_flux = ksB * OMg ; b_flux = ksF * RA2fMg ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 3) += (f_flux - b_flux); _term = ksB ; _MATELM1( 1 ,1) += _term; _MATELM1( 3 ,1) -= _term; _term = ksF ; _MATELM1( 1 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* ~ OMg <-> RA2sMg ( kfB , kfF )*/ f_flux = kfB * OMg ; b_flux = kfF * RA2sMg ; _RHS1( 1) -= (f_flux - b_flux); _term = kfB ; _MATELM1( 1 ,1) += _term; _term = kfF ; _MATELM1( 1 ,0) -= _term; /*REACTION*/ /* ~ RA2fMg <-> RA2Mg ( kfB , kfF )*/ f_flux = kfB * RA2fMg ; b_flux = kfF * RA2Mg ; _RHS1( 3) -= (f_flux - b_flux); _RHS1( 6) += (f_flux - b_flux); _term = kfB ; _MATELM1( 3 ,3) += _term; _MATELM1( 6 ,3) -= _term; _term = kfF ; _MATELM1( 3 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2sMg <-> RA2Mg ( ksB , ksF )*/ f_flux = ksB * RA2sMg ; b_flux = ksF * RA2Mg ; _RHS1( 6) += (f_flux - b_flux); _term = ksB ; _MATELM1( 6 ,0) -= _term; _term = ksF ; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d1Mg ( kd1B , kd1F )*/ f_flux = kd1B * RA2Mg ; b_flux = kd1F * RA2d1Mg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 5) += (f_flux - b_flux); _term = kd1B ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = kd1F ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d2Mg ( kd2B , kd2F )*/ f_flux = kd2B * RA2Mg ; b_flux = kd2F * RA2d2Mg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 4) += (f_flux - b_flux); _term = kd2B ; _MATELM1( 6 ,6) += _term; _MATELM1( 4 ,6) -= _term; _term = kd2F ; _MATELM1( 6 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ RA2Mg <-> RAMg ( ( 2.0 * koff ) , ( kon * T ) )*/ f_flux = ( 2.0 * koff ) * RA2Mg ; b_flux = ( kon * T ) * RAMg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 7) += (f_flux - b_flux); _term = ( 2.0 * koff ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 7 ,6) -= _term; _term = ( kon * T ) ; _MATELM1( 6 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ RAMg <-> RMg ( koff , ( 2.0 * kon * T ) )*/ f_flux = koff * RAMg ; b_flux = ( 2.0 * kon * T ) * RMg ; _RHS1( 7) -= (f_flux - b_flux); _RHS1( 8) += (f_flux - b_flux); _term = koff ; _MATELM1( 7 ,7) += _term; _MATELM1( 8 ,7) -= _term; _term = ( 2.0 * kon * T ) ; _MATELM1( 7 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* R + RA + RA2 + RA2d1 + RA2d2 + RA2f + RA2s + O + OMg + RMg + RAMg + RA2Mg + RA2d1Mg + RA2d2Mg + RA2fMg + RA2sMg = 1.0 */ _RHS1(0) = 1.0; _MATELM1(0, 0) = 1; _RHS1(0) -= RA2sMg ; _MATELM1(0, 3) = 1; _RHS1(0) -= RA2fMg ; _MATELM1(0, 4) = 1; _RHS1(0) -= RA2d2Mg ; _MATELM1(0, 5) = 1; _RHS1(0) -= RA2d1Mg ; _MATELM1(0, 6) = 1; _RHS1(0) -= RA2Mg ; _MATELM1(0, 7) = 1; _RHS1(0) -= RAMg ; _MATELM1(0, 8) = 1; _RHS1(0) -= RMg ; _MATELM1(0, 1) = 1; _RHS1(0) -= OMg ; _MATELM1(0, 2) = 1; _RHS1(0) -= O ; _MATELM1(0, 9) = 1; _RHS1(0) -= RA2s ; _MATELM1(0, 10) = 1; _RHS1(0) -= RA2f ; _MATELM1(0, 11) = 1; _RHS1(0) -= RA2d2 ; _MATELM1(0, 12) = 1; _RHS1(0) -= RA2d1 ; _MATELM1(0, 13) = 1; _RHS1(0) -= RA2 ; _MATELM1(0, 14) = 1; _RHS1(0) -= RA ; _MATELM1(0, 15) = 1; _RHS1(0) -= R ; /*CONSERVATION*/ } return _reset; } #if NET_RECEIVE_BUFFERING #undef t #define t _nrb_t static inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag); void _net_buf_receive(NrnThread* _nt) { if (!_nt->_ml_list) { return; } Memb_list* _ml = _nt->_ml_list[_mechtype]; if (!_ml) { return; } NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer; int _di; int stream_id = _nt->stream_id; Point_process* _pnt = _nt->pntprocs; int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset; int _displ_cnt = _nrb->_displ_cnt; _PRAGMA_FOR_NETRECV_ACC_LOOP_ for (_di = 0; _di < _displ_cnt; ++_di) { int _inrb; int _di0 = _nrb->_displ[_di]; int _di1 = _nrb->_displ[_di + 1]; for (_inrb = _di0; _inrb < _di1; ++_inrb) { int _i = _nrb->_nrb_index[_inrb]; int _j = _nrb->_pnt_index[_i]; int _k = _nrb->_weight_index[_i]; double _nrt = _nrb->_nrb_t[_i]; double _nrflag = _nrb->_nrb_flag[_i]; _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag); } } #pragma acc wait(stream_id) _nrb->_displ_cnt = 0; _nrb->_cnt = 0; /*printf("_net_buf_receive__NMDA16 %d\n", _nt->_id);*/ } void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) { NrnThread* _nt = nrn_threads + _pnt->_tid; NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer; if (_nrb->_cnt >= _nrb->_size){ realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]); } _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs; _nrb->_weight_index[_nrb->_cnt] = _weight_index; _nrb->_nrb_t[_nrb->_cnt] = _nt->_t; _nrb->_nrb_flag[_nrb->_cnt] = _lflag; ++_nrb->_cnt; } static void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag) #else void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) #endif { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0; Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args; NrnThread* _nt; int _tid = _pnt->_tid; _nt = nrn_threads + _tid; _thread = (ThreadDatum*)0; double *_weights = _nt->_weights; _args = _weights + _weight_index; _ml = _nt->_ml_list[_pnt->_type]; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _iml = _pnt->_i_instance; #if LAYOUT == 1 /*AoS*/ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #endif #if LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; #endif #if LAYOUT > 1 /*AoSoA*/ #error AoSoA not implemented. #endif #if !defined(_OPENACC) assert(_tsav <= t); #endif _tsav = t; { if ( _lflag == 0.0 ) { tRel = t ; synon = 1.0 ; w = _args[0] ; } } #if NET_RECEIVE_BUFFERING #undef t #define t _nt->_t #endif } static int rates ( _threadargsprotocomma_ double _lv , double _lt ) { T = T_max * ( _lt - tRel ) / tau * exp ( 1.0 - ( _lt - tRel ) / tau ) * synon ; Kcs = Kcs0 * exp ( _lv / a ) ; kP = kP0 * exp ( _lv / b ) ; kNo = kNo0 * exp ( _lv / c ) ; kNi = kNi0 * exp ( _lv / d ) ; kMgF = kP / ( ( 1.0 + nao / Kna ) * ( 1.0 + nao / Kna + csi / Kcs ) ) ; kMgB = kNo / pow( ( 1.0 + nao / Kna ) , 2.0 ) + kNi ; ksF = ksF0 * exp ( ( _lv - V0 ) / Vdep ) ; ksB = ksB0 * exp ( ( _lv - V0 ) / Vdep * ( - 1.0 ) ) ; kfF = kfF0 * exp ( ( _lv - V0 ) / Vdep ) ; kfB = kfB0 * exp ( ( _lv - V0 ) / Vdep * ( - 1.0 ) ) ; return 0; } #if 0 /*BBCORE*/ static double _hoc_rates(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; rates ( _threadargs_, *getarg(1) , *getarg(2) ); return(_r); } #endif /*BBCORE*/ /*CVODE ode begin*/ static int _ode_spec1(_threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; {int _i; for(_i=0;_i<16;_i++) _p[_dlist1[_i]] = 0.0;} rates ( _threadargscomma_ v , t ) ; /* ~ R <-> RA ( ( 2.0 * kon * T ) , koff )*/ f_flux = ( 2.0 * kon * T ) * R ; b_flux = koff * RA ; DR -= (f_flux - b_flux); DRA += (f_flux - b_flux); /*REACTION*/ /* ~ RA <-> RA2 ( ( kon * T ) , ( 2.0 * koff ) )*/ f_flux = ( kon * T ) * RA ; b_flux = ( 2.0 * koff ) * RA2 ; DRA -= (f_flux - b_flux); DRA2 += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2d1 ( kd1F , kd1B )*/ f_flux = kd1F * RA2 ; b_flux = kd1B * RA2d1 ; DRA2 -= (f_flux - b_flux); DRA2d1 += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2d2 ( kd2F , kd2B )*/ f_flux = kd2F * RA2 ; b_flux = kd2B * RA2d2 ; DRA2 -= (f_flux - b_flux); DRA2d2 += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2f ( kfF , kfB )*/ f_flux = kfF * RA2 ; b_flux = kfB * RA2f ; DRA2 -= (f_flux - b_flux); DRA2f += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2s ( ksF , ksB )*/ f_flux = ksF * RA2 ; b_flux = ksB * RA2s ; DRA2 -= (f_flux - b_flux); DRA2s += (f_flux - b_flux); /*REACTION*/ /* ~ RA2f <-> O ( ksF , ksB )*/ f_flux = ksF * RA2f ; b_flux = ksB * O ; DRA2f -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ RA2s <-> O ( kfF , kfB )*/ f_flux = kfF * RA2s ; b_flux = kfB * O ; DRA2s -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ O <-> OMg ( ( kMgF * Mg ) , kMgB )*/ f_flux = ( kMgF * Mg ) * O ; b_flux = kMgB * OMg ; DO -= (f_flux - b_flux); DOMg += (f_flux - b_flux); /*REACTION*/ /* ~ OMg <-> RA2fMg ( ksB , ksF )*/ f_flux = ksB * OMg ; b_flux = ksF * RA2fMg ; DOMg -= (f_flux - b_flux); DRA2fMg += (f_flux - b_flux); /*REACTION*/ /* ~ OMg <-> RA2sMg ( kfB , kfF )*/ f_flux = kfB * OMg ; b_flux = kfF * RA2sMg ; DOMg -= (f_flux - b_flux); DRA2sMg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2fMg <-> RA2Mg ( kfB , kfF )*/ f_flux = kfB * RA2fMg ; b_flux = kfF * RA2Mg ; DRA2fMg -= (f_flux - b_flux); DRA2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2sMg <-> RA2Mg ( ksB , ksF )*/ f_flux = ksB * RA2sMg ; b_flux = ksF * RA2Mg ; DRA2sMg -= (f_flux - b_flux); DRA2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2Mg <-> RA2d1Mg ( kd1B , kd1F )*/ f_flux = kd1B * RA2Mg ; b_flux = kd1F * RA2d1Mg ; DRA2Mg -= (f_flux - b_flux); DRA2d1Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2Mg <-> RA2d2Mg ( kd2B , kd2F )*/ f_flux = kd2B * RA2Mg ; b_flux = kd2F * RA2d2Mg ; DRA2Mg -= (f_flux - b_flux); DRA2d2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2Mg <-> RAMg ( ( 2.0 * koff ) , ( kon * T ) )*/ f_flux = ( 2.0 * koff ) * RA2Mg ; b_flux = ( kon * T ) * RAMg ; DRA2Mg -= (f_flux - b_flux); DRAMg += (f_flux - b_flux); /*REACTION*/ /* ~ RAMg <-> RMg ( koff , ( 2.0 * kon * T ) )*/ f_flux = koff * RAMg ; b_flux = ( 2.0 * kon * T ) * RMg ; DRAMg -= (f_flux - b_flux); DRMg += (f_flux - b_flux); /*REACTION*/ /* R + RA + RA2 + RA2d1 + RA2d2 + RA2f + RA2s + O + OMg + RMg + RAMg + RA2Mg + RA2d1Mg + RA2d2Mg + RA2fMg + RA2sMg = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE matsol*/ static int _ode_matsol1(void* _so, double* _rhs, _threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; b_flux = f_flux = 0.; {int _i; double _dt1 = 1.0/dt; for(_i=0;_i<16;_i++){ _RHS1(_i) = _dt1*(_p[_dlist1[_i]]); _MATELM1(_i, _i) = _dt1; } } rates ( _threadargscomma_ v , t ) ; /* ~ R <-> RA ( ( 2.0 * kon * T ) , koff )*/ _term = ( 2.0 * kon * T ) ; _MATELM1( 15 ,15) += _term; _MATELM1( 14 ,15) -= _term; _term = koff ; _MATELM1( 15 ,14) -= _term; _MATELM1( 14 ,14) += _term; /*REACTION*/ /* ~ RA <-> RA2 ( ( kon * T ) , ( 2.0 * koff ) )*/ _term = ( kon * T ) ; _MATELM1( 14 ,14) += _term; _MATELM1( 13 ,14) -= _term; _term = ( 2.0 * koff ) ; _MATELM1( 14 ,13) -= _term; _MATELM1( 13 ,13) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d1 ( kd1F , kd1B )*/ _term = kd1F ; _MATELM1( 13 ,13) += _term; _MATELM1( 12 ,13) -= _term; _term = kd1B ; _MATELM1( 13 ,12) -= _term; _MATELM1( 12 ,12) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d2 ( kd2F , kd2B )*/ _term = kd2F ; _MATELM1( 13 ,13) += _term; _MATELM1( 11 ,13) -= _term; _term = kd2B ; _MATELM1( 13 ,11) -= _term; _MATELM1( 11 ,11) += _term; /*REACTION*/ /* ~ RA2 <-> RA2f ( kfF , kfB )*/ _term = kfF ; _MATELM1( 13 ,13) += _term; _MATELM1( 10 ,13) -= _term; _term = kfB ; _MATELM1( 13 ,10) -= _term; _MATELM1( 10 ,10) += _term; /*REACTION*/ /* ~ RA2 <-> RA2s ( ksF , ksB )*/ _term = ksF ; _MATELM1( 13 ,13) += _term; _MATELM1( 9 ,13) -= _term; _term = ksB ; _MATELM1( 13 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ RA2f <-> O ( ksF , ksB )*/ _term = ksF ; _MATELM1( 10 ,10) += _term; _MATELM1( 2 ,10) -= _term; _term = ksB ; _MATELM1( 10 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ RA2s <-> O ( kfF , kfB )*/ _term = kfF ; _MATELM1( 9 ,9) += _term; _MATELM1( 2 ,9) -= _term; _term = kfB ; _MATELM1( 9 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ O <-> OMg ( ( kMgF * Mg ) , kMgB )*/ _term = ( kMgF * Mg ) ; _MATELM1( 2 ,2) += _term; _MATELM1( 1 ,2) -= _term; _term = kMgB ; _MATELM1( 2 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ OMg <-> RA2fMg ( ksB , ksF )*/ _term = ksB ; _MATELM1( 1 ,1) += _term; _MATELM1( 3 ,1) -= _term; _term = ksF ; _MATELM1( 1 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* ~ OMg <-> RA2sMg ( kfB , kfF )*/ _term = kfB ; _MATELM1( 1 ,1) += _term; _MATELM1( 0 ,1) -= _term; _term = kfF ; _MATELM1( 1 ,0) -= _term; _MATELM1( 0 ,0) += _term; /*REACTION*/ /* ~ RA2fMg <-> RA2Mg ( kfB , kfF )*/ _term = kfB ; _MATELM1( 3 ,3) += _term; _MATELM1( 6 ,3) -= _term; _term = kfF ; _MATELM1( 3 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2sMg <-> RA2Mg ( ksB , ksF )*/ _term = ksB ; _MATELM1( 0 ,0) += _term; _MATELM1( 6 ,0) -= _term; _term = ksF ; _MATELM1( 0 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d1Mg ( kd1B , kd1F )*/ _term = kd1B ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = kd1F ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d2Mg ( kd2B , kd2F )*/ _term = kd2B ; _MATELM1( 6 ,6) += _term; _MATELM1( 4 ,6) -= _term; _term = kd2F ; _MATELM1( 6 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ RA2Mg <-> RAMg ( ( 2.0 * koff ) , ( kon * T ) )*/ _term = ( 2.0 * koff ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 7 ,6) -= _term; _term = ( kon * T ) ; _MATELM1( 6 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ RAMg <-> RMg ( koff , ( 2.0 * kon * T ) )*/ _term = koff ; _MATELM1( 7 ,7) += _term; _MATELM1( 8 ,7) -= _term; _term = ( 2.0 * kon * T ) ; _MATELM1( 7 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* R + RA + RA2 + RA2d1 + RA2d2 + RA2f + RA2s + O + OMg + RMg + RAMg + RA2Mg + RA2d1Mg + RA2d2Mg + RA2fMg + RA2sMg = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE end*/ static void _thread_mem_init(ThreadDatum* _thread) { if (_thread1data_inuse) {_thread[_gth]._pval = (double*)ecalloc(10, sizeof(double)); }else{ _thread[_gth]._pval = _thread1data; _thread1data_inuse = 1; } } static void _thread_cleanup(ThreadDatum* _thread) { _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_cvspth1]._pvoid); _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_spth1]._pvoid); if (_thread[_gth]._pval == _thread1data) { _thread1data_inuse = 0; }else{ free((void*)_thread[_gth]._pval); } } static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ OMg = OMg0; O = O0; RA2sMg = RA2sMg0; RA2fMg = RA2fMg0; RA2d2Mg = RA2d2Mg0; RA2d1Mg = RA2d1Mg0; RA2Mg = RA2Mg0; RAMg = RAMg0; RMg = RMg0; RA2s = RA2s0; RA2f = RA2f0; RA2d2 = RA2d20; RA2d1 = RA2d10; RA2 = RA20; RA = RA0; R = R0; { T = 0.0 ; synon = 0.0 ; tRel = 0.0 ; R = 1.0 ; rates ( _threadargscomma_ v , t ) ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; if (!_thread[_spth1]._pvoid) { _thread[_spth1]._pvoid = nrn_cons_sparseobj(kstates_NMDA16{}, 16, _ml, _threadargs_); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_so = (void*) acc_deviceptr(_thread[_spth1]._pvoid); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[_spth1]._pvoid), &_d_so, sizeof(void*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _tsav = -1e20; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V nao = _ion_nao; initmodel(_threadargs_); } } } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { g = w * gmax * O ; i = g * ( v - Erev ) ; } _current += i; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; double * _vec_shadow_rhs = _nt->_shadow_rhs; double * _vec_shadow_d = _nt->_shadow_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V nao = _ion_nao; _g = _nrn_current(_threadargs_, _v + .001); { _rhs = _nrn_current(_threadargs_, _v); } _g = (_g - _rhs)/.001; double _mfact = 1.e2/(_nd_area); _g *= _mfact; _rhs *= _mfact; _PRCELLSTATE_G #ifdef _OPENACC if(_nt->compute_gpu) { #pragma acc atomic update _vec_rhs[_nd_idx] -= _rhs; #pragma acc atomic update _vec_d[_nd_idx] += _g; } else { _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; } #else _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; #endif } #ifdef _OPENACC if(!(_nt->compute_gpu)) { for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; } #else for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; #endif } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { nao = _ion_nao; { sparse_thread(static_cast(_thread[_spth1]._pvoid), 16, _slist1, _dlist1, &t, dt, kstates_NMDA16{}, _linmat1, _threadargs_); }}} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*16); _dlist1 = (int*)malloc(sizeof(int)*16); _slist1[0] = &(RA2sMg) - _p; _dlist1[0] = &(DRA2sMg) - _p; _slist1[1] = &(OMg) - _p; _dlist1[1] = &(DOMg) - _p; _slist1[2] = &(O) - _p; _dlist1[2] = &(DO) - _p; _slist1[3] = &(RA2fMg) - _p; _dlist1[3] = &(DRA2fMg) - _p; _slist1[4] = &(RA2d2Mg) - _p; _dlist1[4] = &(DRA2d2Mg) - _p; _slist1[5] = &(RA2d1Mg) - _p; _dlist1[5] = &(DRA2d1Mg) - _p; _slist1[6] = &(RA2Mg) - _p; _dlist1[6] = &(DRA2Mg) - _p; _slist1[7] = &(RAMg) - _p; _dlist1[7] = &(DRAMg) - _p; _slist1[8] = &(RMg) - _p; _dlist1[8] = &(DRMg) - _p; _slist1[9] = &(RA2s) - _p; _dlist1[9] = &(DRA2s) - _p; _slist1[10] = &(RA2f) - _p; _dlist1[10] = &(DRA2f) - _p; _slist1[11] = &(RA2d2) - _p; _dlist1[11] = &(DRA2d2) - _p; _slist1[12] = &(RA2d1) - _p; _dlist1[12] = &(DRA2d1) - _p; _slist1[13] = &(RA2) - _p; _dlist1[13] = &(DRA2) - _p; _slist1[14] = &(RA) - _p; _dlist1[14] = &(DRA) - _p; _slist1[15] = &(R) - _p; _dlist1[15] = &(DR) - _p; #pragma acc enter data copyin(_slist1[0:16]) #pragma acc enter data copyin(_dlist1[0:16]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/SynNMDA16_2.cpp000066400000000000000000001333631425457616700227750ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:3] , _slist1[0:16], _dlist1[0:16] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #if !defined(NET_RECEIVE_BUFFERING) #define NET_RECEIVE_BUFFERING 1 #endif #define nrn_init _nrn_init__NMDA16_2 #define nrn_cur _nrn_cur__NMDA16_2 #define _nrn_current _nrn_current__NMDA16_2 #define nrn_jacob _nrn_jacob__NMDA16_2 #define nrn_state _nrn_state__NMDA16_2 #define initmodel initmodel__NMDA16_2 #define _net_receive _net_receive__NMDA16_2 #define _net_init _net_init__NMDA16_2 #define nrn_state_launcher nrn_state_NMDA16_2_launcher #define nrn_cur_launcher nrn_cur_NMDA16_2_launcher #define nrn_jacob_launcher nrn_jacob_NMDA16_2_launcher #if NET_RECEIVE_BUFFERING #define _net_buf_receive _net_buf_receive_NMDA16_2 void _net_buf_receive(NrnThread*); #endif #define kstates kstates_NMDA16_2 #define rates rates_NMDA16_2 #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define Erev _p[0*_STRIDE] #define tau _p[1*_STRIDE] #define T_max _p[2*_STRIDE] #define kd1F _p[3*_STRIDE] #define kd1B _p[4*_STRIDE] #define kd2F _p[5*_STRIDE] #define kd2B _p[6*_STRIDE] #define csi _p[7*_STRIDE] #define i _p[8*_STRIDE] #define g _p[9*_STRIDE] #define T _p[10*_STRIDE] #define tRel _p[11*_STRIDE] #define synon _p[12*_STRIDE] #define R _p[13*_STRIDE] #define RA _p[14*_STRIDE] #define RA2 _p[15*_STRIDE] #define RA2d1 _p[16*_STRIDE] #define RA2d2 _p[17*_STRIDE] #define RA2f _p[18*_STRIDE] #define RA2s _p[19*_STRIDE] #define O _p[20*_STRIDE] #define OMg _p[21*_STRIDE] #define RMg _p[22*_STRIDE] #define RAMg _p[23*_STRIDE] #define RA2Mg _p[24*_STRIDE] #define RA2d1Mg _p[25*_STRIDE] #define RA2d2Mg _p[26*_STRIDE] #define RA2fMg _p[27*_STRIDE] #define RA2sMg _p[28*_STRIDE] #define w _p[29*_STRIDE] #define nao _p[30*_STRIDE] #define DR _p[31*_STRIDE] #define DRA _p[32*_STRIDE] #define DRA2 _p[33*_STRIDE] #define DRA2d1 _p[34*_STRIDE] #define DRA2d2 _p[35*_STRIDE] #define DRA2f _p[36*_STRIDE] #define DRA2s _p[37*_STRIDE] #define DO _p[38*_STRIDE] #define DOMg _p[39*_STRIDE] #define DRMg _p[40*_STRIDE] #define DRAMg _p[41*_STRIDE] #define DRA2Mg _p[42*_STRIDE] #define DRA2d1Mg _p[43*_STRIDE] #define DRA2d2Mg _p[44*_STRIDE] #define DRA2fMg _p[45*_STRIDE] #define DRA2sMg _p[46*_STRIDE] #define _v_unused _p[47*_STRIDE] #define _g_unused _p[48*_STRIDE] #define _tsav _p[49*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _nd_area _nt_data[_ppvar[0*_STRIDE]] #define _ion_nao _nt_data[_ppvar[2*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ static double _hoc_rates(); #endif /*BBCORE*/ #define _mechtype _mechtype_NMDA16_2 int _mechtype; #pragma acc declare copyin (_mechtype) static int _pointtype; #if 0 /*BBCORE*/ static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process(); return create_point_process(_pointtype, _ho); } static void _hoc_destroy_pnt(); static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process(); return loc_point_process(_pointtype, _vptr); } static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point(); return has_loc_point(_vptr); } static double _hoc_get_loc_pnt(_vptr)void* _vptr; { double get_loc_point_process(); return (get_loc_point_process(_vptr)); } #endif /*BBCORE*/ #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { 0,0 }; static Member_func _member_func[] = { "loc", _hoc_loc_pnt, "has_loc", _hoc_has_loc, "get_loc", _hoc_get_loc_pnt, "rates", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ static int _thread1data_inuse = 0; static double _thread1data[6]; #define _gth 2 #define Kcs0 Kcs0_NMDA16_2 double Kcs0 = 0.27; #pragma acc declare copyin (Kcs0) #define Kna Kna_NMDA16_2 double Kna = 34.4; #pragma acc declare copyin (Kna) #define Kcs Kcs_NMDA16_2 double Kcs = 0; #pragma acc declare copyin (Kcs) #define Mg Mg_NMDA16_2 double Mg = 1; #pragma acc declare copyin (Mg) #define V0 V0_NMDA16_2 double V0 = -100; #pragma acc declare copyin (V0) #define Vdep Vdep_NMDA16_2 double Vdep = 175; #pragma acc declare copyin (Vdep) #define a a_NMDA16_2 double a = -21; #pragma acc declare copyin (a) #define b b_NMDA16_2 double b = -55; #pragma acc declare copyin (b) #define c c_NMDA16_2 double c = 52.7; #pragma acc declare copyin (c) #define d d_NMDA16_2 double d = -50; #pragma acc declare copyin (d) #define gmax gmax_NMDA16_2 double gmax = 50; #pragma acc declare copyin (gmax) #define kNi0 kNi0_NMDA16_2 double kNi0 = 0.0618; #pragma acc declare copyin (kNi0) #define kNo0 kNo0_NMDA16_2 double kNo0 = 110; #pragma acc declare copyin (kNo0) #define kP0 kP0_NMDA16_2 double kP0 = 1100; #pragma acc declare copyin (kP0) #define kfB0 kfB0_NMDA16_2 double kfB0 = 0.175; #pragma acc declare copyin (kfB0) #define kfF0 kfF0_NMDA16_2 double kfF0 = 2.836; #pragma acc declare copyin (kfF0) #define ksB0 ksB0_NMDA16_2 double ksB0 = 0.23; #pragma acc declare copyin (ksB0) #define ksF0 ksF0_NMDA16_2 double ksF0 = 0.048; #pragma acc declare copyin (ksF0) #define koff koff_NMDA16_2 double koff = 0.0381; #pragma acc declare copyin (koff) #define kon kon_NMDA16_2 double kon = 2.83; #pragma acc declare copyin (kon) #define kfB_NMDA16_2 _thread1data[0] #define kfB _thread[_gth]._pval[0] #define kfF_NMDA16_2 _thread1data[1] #define kfF _thread[_gth]._pval[1] #define ksB_NMDA16_2 _thread1data[2] #define ksB _thread[_gth]._pval[2] #define ksF_NMDA16_2 _thread1data[3] #define ksF _thread[_gth]._pval[3] #define kMgB_NMDA16_2 _thread1data[4] #define kMgB _thread[_gth]._pval[4] #define kMgF_NMDA16_2 _thread1data[5] #define kMgF _thread[_gth]._pval[5] #define kNi kNi_NMDA16_2 double kNi = 0; #pragma acc declare copyin (kNi) #define kNo kNo_NMDA16_2 double kNo = 0; #pragma acc declare copyin (kNo) #define kP kP_NMDA16_2 double kP = 0; #pragma acc declare copyin (kP) static void _acc_globals_update() { #pragma acc update device (Kcs0) if(nrn_threads->compute_gpu) #pragma acc update device (Kna) if(nrn_threads->compute_gpu) #pragma acc update device (Kcs) if(nrn_threads->compute_gpu) #pragma acc update device (Mg) if(nrn_threads->compute_gpu) #pragma acc update device (V0) if(nrn_threads->compute_gpu) #pragma acc update device (Vdep) if(nrn_threads->compute_gpu) #pragma acc update device (a) if(nrn_threads->compute_gpu) #pragma acc update device (b) if(nrn_threads->compute_gpu) #pragma acc update device (c) if(nrn_threads->compute_gpu) #pragma acc update device (d) if(nrn_threads->compute_gpu) #pragma acc update device (gmax) if(nrn_threads->compute_gpu) #pragma acc update device (kNi0) if(nrn_threads->compute_gpu) #pragma acc update device (kNo0) if(nrn_threads->compute_gpu) #pragma acc update device (kP0) if(nrn_threads->compute_gpu) #pragma acc update device (kfB0) if(nrn_threads->compute_gpu) #pragma acc update device (kfF0) if(nrn_threads->compute_gpu) #pragma acc update device (ksB0) if(nrn_threads->compute_gpu) #pragma acc update device (ksF0) if(nrn_threads->compute_gpu) #pragma acc update device (koff) if(nrn_threads->compute_gpu) #pragma acc update device (kon) if(nrn_threads->compute_gpu) #pragma acc update device (kNi) if(nrn_threads->compute_gpu) #pragma acc update device (kNo) if(nrn_threads->compute_gpu) #pragma acc update device (kP) if(nrn_threads->compute_gpu) } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "tau", 1e-09, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "gmax_NMDA16_2", "pS", "Mg_NMDA16_2", "mM", "kon_NMDA16_2", "/ms", "koff_NMDA16_2", "/ms", "ksF0_NMDA16_2", "/ms", "ksB0_NMDA16_2", "/ms", "kfF0_NMDA16_2", "/ms", "kfB0_NMDA16_2", "/ms", "Vdep_NMDA16_2", "mV", "V0_NMDA16_2", "mV", "Kna_NMDA16_2", "mM", "Kcs0_NMDA16_2", "mM", "a_NMDA16_2", "mV", "kP0_NMDA16_2", "/ms", "b_NMDA16_2", "mV", "kNo0_NMDA16_2", "/ms", "c_NMDA16_2", "mV", "kNi0_NMDA16_2", "/ms", "d_NMDA16_2", "mV", "ksF_NMDA16_2", "/ms", "ksB_NMDA16_2", "/ms", "kfF_NMDA16_2", "/ms", "kfB_NMDA16_2", "/ms", "kMgF_NMDA16_2", "/ms /mM", "kMgB_NMDA16_2", "/ms", "Kcs_NMDA16_2", "mM", "kP_NMDA16_2", "/ms /mM", "kNo_NMDA16_2", "/ms", "kNi_NMDA16_2", "/ms", "Erev", "mV", "tau", "ms", "T_max", "mM", "kd1F", "/ms", "kd1B", "/ms", "kd2F", "/ms", "kd2B", "/ms", "csi", "mM", "i", "nA", "g", "uS", "T", "mM", "tRel", "ms", 0,0 }; #endif /*BBCORE*/ static double OMg0 = 0; #pragma acc declare copyin(OMg0) static double O0 = 0; #pragma acc declare copyin(O0) static double RA2sMg0 = 0; #pragma acc declare copyin(RA2sMg0) static double RA2fMg0 = 0; #pragma acc declare copyin(RA2fMg0) static double RA2d2Mg0 = 0; #pragma acc declare copyin(RA2d2Mg0) static double RA2d1Mg0 = 0; #pragma acc declare copyin(RA2d1Mg0) static double RA2Mg0 = 0; #pragma acc declare copyin(RA2Mg0) static double RAMg0 = 0; #pragma acc declare copyin(RAMg0) static double RMg0 = 0; #pragma acc declare copyin(RMg0) static double RA2s0 = 0; #pragma acc declare copyin(RA2s0) static double RA2f0 = 0; #pragma acc declare copyin(RA2f0) static double RA2d20 = 0; #pragma acc declare copyin(RA2d20) static double RA2d10 = 0; #pragma acc declare copyin(RA2d10) static double RA20 = 0; #pragma acc declare copyin(RA20) static double RA0 = 0; #pragma acc declare copyin(RA0) static double R0 = 0; #pragma acc declare copyin(R0) static double delta_t = 1; #pragma acc declare copyin(delta_t) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "gmax_NMDA16_2", &gmax_NMDA16_2, "Mg_NMDA16_2", &Mg_NMDA16_2, "kon_NMDA16_2", &kon_NMDA16_2, "koff_NMDA16_2", &koff_NMDA16_2, "ksF0_NMDA16_2", &ksF0_NMDA16_2, "ksB0_NMDA16_2", &ksB0_NMDA16_2, "kfF0_NMDA16_2", &kfF0_NMDA16_2, "kfB0_NMDA16_2", &kfB0_NMDA16_2, "Vdep_NMDA16_2", &Vdep_NMDA16_2, "V0_NMDA16_2", &V0_NMDA16_2, "Kna_NMDA16_2", &Kna_NMDA16_2, "Kcs0_NMDA16_2", &Kcs0_NMDA16_2, "a_NMDA16_2", &a_NMDA16_2, "kP0_NMDA16_2", &kP0_NMDA16_2, "b_NMDA16_2", &b_NMDA16_2, "kNo0_NMDA16_2", &kNo0_NMDA16_2, "c_NMDA16_2", &c_NMDA16_2, "kNi0_NMDA16_2", &kNi0_NMDA16_2, "d_NMDA16_2", &d_NMDA16_2, "ksF_NMDA16_2", &ksF_NMDA16_2, "ksB_NMDA16_2", &ksB_NMDA16_2, "kfF_NMDA16_2", &kfF_NMDA16_2, "kfB_NMDA16_2", &kfB_NMDA16_2, "kMgF_NMDA16_2", &kMgF_NMDA16_2, "kMgB_NMDA16_2", &kMgB_NMDA16_2, "Kcs_NMDA16_2", &Kcs_NMDA16_2, "kP_NMDA16_2", &kP_NMDA16_2, "kNo_NMDA16_2", &kNo_NMDA16_2, "kNi_NMDA16_2", &kNi_NMDA16_2, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); #if 0 /*BBCORE*/ static void _hoc_destroy_pnt(_vptr) void* _vptr; { destroy_point_process(_vptr); } #endif /*BBCORE*/ /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "NMDA16_2", "Erev", "tau", "T_max", "kd1F", "kd1B", "kd2F", "kd2B", "csi", 0, "i", "g", "T", "tRel", "synon", 0, "R", "RA", "RA2", "RA2d1", "RA2d2", "RA2f", "RA2s", "O", "OMg", "RMg", "RAMg", "RA2Mg", "RA2d1Mg", "RA2d2Mg", "RA2fMg", "RA2sMg", 0, 0}; static int _na_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ Erev = -0.7; tau = 0.3; T_max = 1.5; kd1F = 0.55; kd1B = 0.081; kd2F = 0.32319; kd2B = 0.00020977; csi = 148; prop_ion = need_memb(_na_sym); nrn_promote(prop_ion, 1, 0); _ppvar[2]._pval = &prop_ion->param[2]; /* nao */ #endif /* BBCORE */ } static void _initlists(); #define _tqitem &(_nt->_vdata[_ppvar[3*_STRIDE]]) #if NET_RECEIVE_BUFFERING #undef _tqitem #define _tqitem _ppvar[3*_STRIDE] #endif void _net_receive(Point_process*, int, double); static void _thread_mem_init(ThreadDatum*); static void _thread_cleanup(ThreadDatum*); static void _update_ion_pointer(Datum*); #define _psize 50 #define _ppsize 4 void _SynNMDA16_2_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _na_type = nrn_get_mechtype("na_ion"); #if 0 /*BBCORE*/ ion_reg("na", -10000.); _na_sym = hoc_lookup("na_ion"); #endif /*BBCORE*/ _pointtype = point_register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/ 4); _extcall_thread = (ThreadDatum*)ecalloc(3, sizeof(ThreadDatum)); _thread_mem_init(_extcall_thread); _thread1data_inuse = 0; _nrn_thread_reg1(_mechtype, _thread_mem_init); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "area"); hoc_register_dparam_semantics(_mechtype, 1, "pntproc"); hoc_register_dparam_semantics(_mechtype, 2, "na_ion"); hoc_register_dparam_semantics(_mechtype, 3, "netsend"); #if NET_RECEIVE_BUFFERING hoc_register_net_receive_buffering(_net_buf_receive, _mechtype); #endif #if NET_RECEIVE_BUFFERING hoc_register_net_send_buffering(_mechtype); #endif set_pnt_receive(_mechtype, _net_receive, nullptr, 1); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "Voltage-dependent kinetic model of NMDA receptor"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int rates(_threadargsprotocomma_ double, double); #define _MATELM1(_row,_col) _nrn_thread_getelm((SparseObj*)_so, _row + 1, _col + 1, _iml)[_iml] #define _RHS1(_arg) _rhs[(_arg+1)*_STRIDE] #define _linmat1 1 static int _spth1 = 1; static int _cvspth1 = 0; static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ #define _slist1 _slist1_NMDA16_2 int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_NMDA16_2 int* _dlist1; #pragma acc declare create(_dlist1) /* _kinetic_ kstates _NMDA16_2 */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct kstates_NMDA16_2 { int operator()(SparseObj* _so, double* _rhs, _threadargsproto_) const; }; int kstates_NMDA16_2::operator() (SparseObj* _so, double* _rhs, _threadargsproto_) const {int _reset=0; { double b_flux, f_flux, _term; int _i; {int _i; double _dt1 = 1.0/dt; for(_i=1;_i<16;_i++){ _RHS1(_i) = -_dt1*(_p[_slist1[_i]*_STRIDE] - _p[_dlist1[_i]*_STRIDE]); _MATELM1(_i, _i) = _dt1; } } rates ( _threadargscomma_ v , t ) ; /* ~ R <-> RA ( ( 2.0 * kon * T ) , koff )*/ f_flux = ( 2.0 * kon * T ) * R ; b_flux = koff * RA ; _RHS1( 15) -= (f_flux - b_flux); _RHS1( 14) += (f_flux - b_flux); _term = ( 2.0 * kon * T ) ; _MATELM1( 15 ,15) += _term; _MATELM1( 14 ,15) -= _term; _term = koff ; _MATELM1( 15 ,14) -= _term; _MATELM1( 14 ,14) += _term; /*REACTION*/ /* ~ RA <-> RA2 ( ( kon * T ) , ( 2.0 * koff ) )*/ f_flux = ( kon * T ) * RA ; b_flux = ( 2.0 * koff ) * RA2 ; _RHS1( 14) -= (f_flux - b_flux); _RHS1( 13) += (f_flux - b_flux); _term = ( kon * T ) ; _MATELM1( 14 ,14) += _term; _MATELM1( 13 ,14) -= _term; _term = ( 2.0 * koff ) ; _MATELM1( 14 ,13) -= _term; _MATELM1( 13 ,13) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d1 ( kd1F , kd1B )*/ f_flux = kd1F * RA2 ; b_flux = kd1B * RA2d1 ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 12) += (f_flux - b_flux); _term = kd1F ; _MATELM1( 13 ,13) += _term; _MATELM1( 12 ,13) -= _term; _term = kd1B ; _MATELM1( 13 ,12) -= _term; _MATELM1( 12 ,12) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d2 ( kd2F , kd2B )*/ f_flux = kd2F * RA2 ; b_flux = kd2B * RA2d2 ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 11) += (f_flux - b_flux); _term = kd2F ; _MATELM1( 13 ,13) += _term; _MATELM1( 11 ,13) -= _term; _term = kd2B ; _MATELM1( 13 ,11) -= _term; _MATELM1( 11 ,11) += _term; /*REACTION*/ /* ~ RA2 <-> RA2f ( kfF , kfB )*/ f_flux = kfF * RA2 ; b_flux = kfB * RA2f ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 10) += (f_flux - b_flux); _term = kfF ; _MATELM1( 13 ,13) += _term; _MATELM1( 10 ,13) -= _term; _term = kfB ; _MATELM1( 13 ,10) -= _term; _MATELM1( 10 ,10) += _term; /*REACTION*/ /* ~ RA2 <-> RA2s ( ksF , ksB )*/ f_flux = ksF * RA2 ; b_flux = ksB * RA2s ; _RHS1( 13) -= (f_flux - b_flux); _RHS1( 9) += (f_flux - b_flux); _term = ksF ; _MATELM1( 13 ,13) += _term; _MATELM1( 9 ,13) -= _term; _term = ksB ; _MATELM1( 13 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ RA2f <-> O ( ksF , ksB )*/ f_flux = ksF * RA2f ; b_flux = ksB * O ; _RHS1( 10) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = ksF ; _MATELM1( 10 ,10) += _term; _MATELM1( 2 ,10) -= _term; _term = ksB ; _MATELM1( 10 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ RA2s <-> O ( kfF , kfB )*/ f_flux = kfF * RA2s ; b_flux = kfB * O ; _RHS1( 9) -= (f_flux - b_flux); _RHS1( 2) += (f_flux - b_flux); _term = kfF ; _MATELM1( 9 ,9) += _term; _MATELM1( 2 ,9) -= _term; _term = kfB ; _MATELM1( 9 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ O <-> OMg ( ( kMgF * Mg ) , kMgB )*/ f_flux = ( kMgF * Mg ) * O ; b_flux = kMgB * OMg ; _RHS1( 2) -= (f_flux - b_flux); _RHS1( 1) += (f_flux - b_flux); _term = ( kMgF * Mg ) ; _MATELM1( 2 ,2) += _term; _MATELM1( 1 ,2) -= _term; _term = kMgB ; _MATELM1( 2 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ OMg <-> RA2fMg ( ksB , ksF )*/ f_flux = ksB * OMg ; b_flux = ksF * RA2fMg ; _RHS1( 1) -= (f_flux - b_flux); _RHS1( 3) += (f_flux - b_flux); _term = ksB ; _MATELM1( 1 ,1) += _term; _MATELM1( 3 ,1) -= _term; _term = ksF ; _MATELM1( 1 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* ~ OMg <-> RA2sMg ( kfB , kfF )*/ f_flux = kfB * OMg ; b_flux = kfF * RA2sMg ; _RHS1( 1) -= (f_flux - b_flux); _term = kfB ; _MATELM1( 1 ,1) += _term; _term = kfF ; _MATELM1( 1 ,0) -= _term; /*REACTION*/ /* ~ RA2fMg <-> RA2Mg ( kfB , kfF )*/ f_flux = kfB * RA2fMg ; b_flux = kfF * RA2Mg ; _RHS1( 3) -= (f_flux - b_flux); _RHS1( 6) += (f_flux - b_flux); _term = kfB ; _MATELM1( 3 ,3) += _term; _MATELM1( 6 ,3) -= _term; _term = kfF ; _MATELM1( 3 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2sMg <-> RA2Mg ( ksB , ksF )*/ f_flux = ksB * RA2sMg ; b_flux = ksF * RA2Mg ; _RHS1( 6) += (f_flux - b_flux); _term = ksB ; _MATELM1( 6 ,0) -= _term; _term = ksF ; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d1Mg ( kd1B , kd1F )*/ f_flux = kd1B * RA2Mg ; b_flux = kd1F * RA2d1Mg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 5) += (f_flux - b_flux); _term = kd1B ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = kd1F ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d2Mg ( kd2B , kd2F )*/ f_flux = kd2B * RA2Mg ; b_flux = kd2F * RA2d2Mg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 4) += (f_flux - b_flux); _term = kd2B ; _MATELM1( 6 ,6) += _term; _MATELM1( 4 ,6) -= _term; _term = kd2F ; _MATELM1( 6 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ RA2Mg <-> RAMg ( ( 2.0 * koff ) , ( kon * T ) )*/ f_flux = ( 2.0 * koff ) * RA2Mg ; b_flux = ( kon * T ) * RAMg ; _RHS1( 6) -= (f_flux - b_flux); _RHS1( 7) += (f_flux - b_flux); _term = ( 2.0 * koff ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 7 ,6) -= _term; _term = ( kon * T ) ; _MATELM1( 6 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ RAMg <-> RMg ( koff , ( 2.0 * kon * T ) )*/ f_flux = koff * RAMg ; b_flux = ( 2.0 * kon * T ) * RMg ; _RHS1( 7) -= (f_flux - b_flux); _RHS1( 8) += (f_flux - b_flux); _term = koff ; _MATELM1( 7 ,7) += _term; _MATELM1( 8 ,7) -= _term; _term = ( 2.0 * kon * T ) ; _MATELM1( 7 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* R + RA + RA2 + RA2d1 + RA2d2 + RA2f + RA2s + O + OMg + RMg + RAMg + RA2Mg + RA2d1Mg + RA2d2Mg + RA2fMg + RA2sMg = 1.0 */ _RHS1(0) = 1.0; _MATELM1(0, 0) = 1; _RHS1(0) -= RA2sMg ; _MATELM1(0, 3) = 1; _RHS1(0) -= RA2fMg ; _MATELM1(0, 4) = 1; _RHS1(0) -= RA2d2Mg ; _MATELM1(0, 5) = 1; _RHS1(0) -= RA2d1Mg ; _MATELM1(0, 6) = 1; _RHS1(0) -= RA2Mg ; _MATELM1(0, 7) = 1; _RHS1(0) -= RAMg ; _MATELM1(0, 8) = 1; _RHS1(0) -= RMg ; _MATELM1(0, 1) = 1; _RHS1(0) -= OMg ; _MATELM1(0, 2) = 1; _RHS1(0) -= O ; _MATELM1(0, 9) = 1; _RHS1(0) -= RA2s ; _MATELM1(0, 10) = 1; _RHS1(0) -= RA2f ; _MATELM1(0, 11) = 1; _RHS1(0) -= RA2d2 ; _MATELM1(0, 12) = 1; _RHS1(0) -= RA2d1 ; _MATELM1(0, 13) = 1; _RHS1(0) -= RA2 ; _MATELM1(0, 14) = 1; _RHS1(0) -= RA ; _MATELM1(0, 15) = 1; _RHS1(0) -= R ; /*CONSERVATION*/ } return _reset; } #if NET_RECEIVE_BUFFERING #undef t #define t _nrb_t static inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag); void _net_buf_receive(NrnThread* _nt) { if (!_nt->_ml_list) { return; } Memb_list* _ml = _nt->_ml_list[_mechtype]; if (!_ml) { return; } NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer; int _di; int stream_id = _nt->stream_id; Point_process* _pnt = _nt->pntprocs; int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset; int _displ_cnt = _nrb->_displ_cnt; _PRAGMA_FOR_NETRECV_ACC_LOOP_ for (_di = 0; _di < _displ_cnt; ++_di) { int _inrb; int _di0 = _nrb->_displ[_di]; int _di1 = _nrb->_displ[_di + 1]; for (_inrb = _di0; _inrb < _di1; ++_inrb) { int _i = _nrb->_nrb_index[_inrb]; int _j = _nrb->_pnt_index[_i]; int _k = _nrb->_weight_index[_i]; double _nrt = _nrb->_nrb_t[_i]; double _nrflag = _nrb->_nrb_flag[_i]; _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag); } } #pragma acc wait(stream_id) _nrb->_displ_cnt = 0; _nrb->_cnt = 0; /*printf("_net_buf_receive__NMDA16_2 %d\n", _nt->_id);*/ { NetSendBuffer_t* _nsb = _ml->_net_send_buffer; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu) update_net_send_buffer_on_host(_nt, _nsb); #endif int _i; for (_i=0; _i < _nsb->_cnt; ++_i) { net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i], _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i], _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]); } _nsb->_cnt = 0; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update device(_nsb->_cnt) if (_nt->compute_gpu) #endif } } static void _net_send_buffering(NetSendBuffer_t* _nsb, int _sendtype, int _i_vdata, int _weight_index, int _ipnt, double _t, double _flag) { int _i = 0; #pragma acc atomic capture _i = _nsb->_cnt++; #if !defined(_OPENACC) if (_i >= _nsb->_size) { _nsb->grow(); } #endif if (_i < _nsb->_size) { _nsb->_sendtype[_i] = _sendtype; _nsb->_vdata_index[_i] = _i_vdata; _nsb->_weight_index[_i] = _weight_index; _nsb->_pnt_index[_i] = _ipnt; _nsb->_nsb_t[_i] = _t; _nsb->_nsb_flag[_i] = _flag; } } void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) { NrnThread* _nt = nrn_threads + _pnt->_tid; NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer; if (_nrb->_cnt >= _nrb->_size){ realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]); } _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs; _nrb->_weight_index[_nrb->_cnt] = _weight_index; _nrb->_nrb_t[_nrb->_cnt] = _nt->_t; _nrb->_nrb_flag[_nrb->_cnt] = _lflag; ++_nrb->_cnt; } static void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag) #else void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) #endif { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0; Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args; NrnThread* _nt; int _tid = _pnt->_tid; _nt = nrn_threads + _tid; _thread = (ThreadDatum*)0; double *_weights = _nt->_weights; _args = _weights + _weight_index; _ml = _nt->_ml_list[_pnt->_type]; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _iml = _pnt->_i_instance; #if LAYOUT == 1 /*AoS*/ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #endif #if LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; #endif #if LAYOUT > 1 /*AoSoA*/ #error AoSoA not implemented. #endif #if !defined(_OPENACC) assert(_tsav <= t); #endif _tsav = t; #if !NET_RECEIVE_BUFFERING if (_lflag == 1. ) {*(_tqitem) = 0;} #endif { if ( _lflag == 0.0 ) { tRel = t ; synon = 1.0 ; w = _args[0] ; } if ( _lflag == 1.0 ) { R = 1.0 ; RA = 0.0 ; RA2 = 0.0 ; RA2d1 = 0.0 ; RA2d2 = 0.0 ; RA2f = 0.0 ; RA2s = 0.0 ; O = 0.0 ; OMg = 0.0 ; RMg = 0.0 ; RAMg = 0.0 ; RA2Mg = 0.0 ; RA2d1Mg = 0.0 ; RA2d2Mg = 0.0 ; RA2fMg = 0.0 ; RA2sMg = 0.0 ; } } #if NET_RECEIVE_BUFFERING #undef t #define t _nt->_t #endif } static int rates ( _threadargsprotocomma_ double _lv , double _lt ) { T = T_max * ( _lt - tRel ) / tau * exp ( 1.0 - ( _lt - tRel ) / tau ) * synon ; kMgF = 610e-3 * exp ( 1.0 * - _lv / 17.0 ) * 1.0 ; kMgB = 5400e-3 * exp ( 1.0 * _lv / 47.0 ) * 1.0 ; ksF = ksF0 * exp ( ( _lv - V0 ) / Vdep ) ; ksB = ksB0 * exp ( ( _lv - V0 ) / Vdep * ( - 1.0 ) ) ; kfF = kfF0 * exp ( ( _lv - V0 ) / Vdep ) ; kfB = kfB0 * exp ( ( _lv - V0 ) / Vdep * ( - 1.0 ) ) ; return 0; } #if 0 /*BBCORE*/ static double _hoc_rates(void* _vptr) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; _p = ((Point_process*)_vptr)->_prop->param; _ppvar = ((Point_process*)_vptr)->_prop->dparam; _thread = _extcall_thread; _nt = (NrnThread*)((Point_process*)_vptr)->_vnt; _r = 1.; rates ( _threadargs_, *getarg(1) , *getarg(2) ); return(_r); } #endif /*BBCORE*/ /*CVODE ode begin*/ static int _ode_spec1(_threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; {int _i; for(_i=0;_i<16;_i++) _p[_dlist1[_i]] = 0.0;} rates ( _threadargscomma_ v , t ) ; /* ~ R <-> RA ( ( 2.0 * kon * T ) , koff )*/ f_flux = ( 2.0 * kon * T ) * R ; b_flux = koff * RA ; DR -= (f_flux - b_flux); DRA += (f_flux - b_flux); /*REACTION*/ /* ~ RA <-> RA2 ( ( kon * T ) , ( 2.0 * koff ) )*/ f_flux = ( kon * T ) * RA ; b_flux = ( 2.0 * koff ) * RA2 ; DRA -= (f_flux - b_flux); DRA2 += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2d1 ( kd1F , kd1B )*/ f_flux = kd1F * RA2 ; b_flux = kd1B * RA2d1 ; DRA2 -= (f_flux - b_flux); DRA2d1 += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2d2 ( kd2F , kd2B )*/ f_flux = kd2F * RA2 ; b_flux = kd2B * RA2d2 ; DRA2 -= (f_flux - b_flux); DRA2d2 += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2f ( kfF , kfB )*/ f_flux = kfF * RA2 ; b_flux = kfB * RA2f ; DRA2 -= (f_flux - b_flux); DRA2f += (f_flux - b_flux); /*REACTION*/ /* ~ RA2 <-> RA2s ( ksF , ksB )*/ f_flux = ksF * RA2 ; b_flux = ksB * RA2s ; DRA2 -= (f_flux - b_flux); DRA2s += (f_flux - b_flux); /*REACTION*/ /* ~ RA2f <-> O ( ksF , ksB )*/ f_flux = ksF * RA2f ; b_flux = ksB * O ; DRA2f -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ RA2s <-> O ( kfF , kfB )*/ f_flux = kfF * RA2s ; b_flux = kfB * O ; DRA2s -= (f_flux - b_flux); DO += (f_flux - b_flux); /*REACTION*/ /* ~ O <-> OMg ( ( kMgF * Mg ) , kMgB )*/ f_flux = ( kMgF * Mg ) * O ; b_flux = kMgB * OMg ; DO -= (f_flux - b_flux); DOMg += (f_flux - b_flux); /*REACTION*/ /* ~ OMg <-> RA2fMg ( ksB , ksF )*/ f_flux = ksB * OMg ; b_flux = ksF * RA2fMg ; DOMg -= (f_flux - b_flux); DRA2fMg += (f_flux - b_flux); /*REACTION*/ /* ~ OMg <-> RA2sMg ( kfB , kfF )*/ f_flux = kfB * OMg ; b_flux = kfF * RA2sMg ; DOMg -= (f_flux - b_flux); DRA2sMg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2fMg <-> RA2Mg ( kfB , kfF )*/ f_flux = kfB * RA2fMg ; b_flux = kfF * RA2Mg ; DRA2fMg -= (f_flux - b_flux); DRA2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2sMg <-> RA2Mg ( ksB , ksF )*/ f_flux = ksB * RA2sMg ; b_flux = ksF * RA2Mg ; DRA2sMg -= (f_flux - b_flux); DRA2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2Mg <-> RA2d1Mg ( kd1B , kd1F )*/ f_flux = kd1B * RA2Mg ; b_flux = kd1F * RA2d1Mg ; DRA2Mg -= (f_flux - b_flux); DRA2d1Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2Mg <-> RA2d2Mg ( kd2B , kd2F )*/ f_flux = kd2B * RA2Mg ; b_flux = kd2F * RA2d2Mg ; DRA2Mg -= (f_flux - b_flux); DRA2d2Mg += (f_flux - b_flux); /*REACTION*/ /* ~ RA2Mg <-> RAMg ( ( 2.0 * koff ) , ( kon * T ) )*/ f_flux = ( 2.0 * koff ) * RA2Mg ; b_flux = ( kon * T ) * RAMg ; DRA2Mg -= (f_flux - b_flux); DRAMg += (f_flux - b_flux); /*REACTION*/ /* ~ RAMg <-> RMg ( koff , ( 2.0 * kon * T ) )*/ f_flux = koff * RAMg ; b_flux = ( 2.0 * kon * T ) * RMg ; DRAMg -= (f_flux - b_flux); DRMg += (f_flux - b_flux); /*REACTION*/ /* R + RA + RA2 + RA2d1 + RA2d2 + RA2f + RA2s + O + OMg + RMg + RAMg + RA2Mg + RA2d1Mg + RA2d2Mg + RA2fMg + RA2sMg = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE matsol*/ static int _ode_matsol1(void* _so, double* _rhs, _threadargsproto_) {int _reset=0;{ double b_flux, f_flux, _term; int _i; b_flux = f_flux = 0.; {int _i; double _dt1 = 1.0/dt; for(_i=0;_i<16;_i++){ _RHS1(_i) = _dt1*(_p[_dlist1[_i]]); _MATELM1(_i, _i) = _dt1; } } rates ( _threadargscomma_ v , t ) ; /* ~ R <-> RA ( ( 2.0 * kon * T ) , koff )*/ _term = ( 2.0 * kon * T ) ; _MATELM1( 15 ,15) += _term; _MATELM1( 14 ,15) -= _term; _term = koff ; _MATELM1( 15 ,14) -= _term; _MATELM1( 14 ,14) += _term; /*REACTION*/ /* ~ RA <-> RA2 ( ( kon * T ) , ( 2.0 * koff ) )*/ _term = ( kon * T ) ; _MATELM1( 14 ,14) += _term; _MATELM1( 13 ,14) -= _term; _term = ( 2.0 * koff ) ; _MATELM1( 14 ,13) -= _term; _MATELM1( 13 ,13) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d1 ( kd1F , kd1B )*/ _term = kd1F ; _MATELM1( 13 ,13) += _term; _MATELM1( 12 ,13) -= _term; _term = kd1B ; _MATELM1( 13 ,12) -= _term; _MATELM1( 12 ,12) += _term; /*REACTION*/ /* ~ RA2 <-> RA2d2 ( kd2F , kd2B )*/ _term = kd2F ; _MATELM1( 13 ,13) += _term; _MATELM1( 11 ,13) -= _term; _term = kd2B ; _MATELM1( 13 ,11) -= _term; _MATELM1( 11 ,11) += _term; /*REACTION*/ /* ~ RA2 <-> RA2f ( kfF , kfB )*/ _term = kfF ; _MATELM1( 13 ,13) += _term; _MATELM1( 10 ,13) -= _term; _term = kfB ; _MATELM1( 13 ,10) -= _term; _MATELM1( 10 ,10) += _term; /*REACTION*/ /* ~ RA2 <-> RA2s ( ksF , ksB )*/ _term = ksF ; _MATELM1( 13 ,13) += _term; _MATELM1( 9 ,13) -= _term; _term = ksB ; _MATELM1( 13 ,9) -= _term; _MATELM1( 9 ,9) += _term; /*REACTION*/ /* ~ RA2f <-> O ( ksF , ksB )*/ _term = ksF ; _MATELM1( 10 ,10) += _term; _MATELM1( 2 ,10) -= _term; _term = ksB ; _MATELM1( 10 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ RA2s <-> O ( kfF , kfB )*/ _term = kfF ; _MATELM1( 9 ,9) += _term; _MATELM1( 2 ,9) -= _term; _term = kfB ; _MATELM1( 9 ,2) -= _term; _MATELM1( 2 ,2) += _term; /*REACTION*/ /* ~ O <-> OMg ( ( kMgF * Mg ) , kMgB )*/ _term = ( kMgF * Mg ) ; _MATELM1( 2 ,2) += _term; _MATELM1( 1 ,2) -= _term; _term = kMgB ; _MATELM1( 2 ,1) -= _term; _MATELM1( 1 ,1) += _term; /*REACTION*/ /* ~ OMg <-> RA2fMg ( ksB , ksF )*/ _term = ksB ; _MATELM1( 1 ,1) += _term; _MATELM1( 3 ,1) -= _term; _term = ksF ; _MATELM1( 1 ,3) -= _term; _MATELM1( 3 ,3) += _term; /*REACTION*/ /* ~ OMg <-> RA2sMg ( kfB , kfF )*/ _term = kfB ; _MATELM1( 1 ,1) += _term; _MATELM1( 0 ,1) -= _term; _term = kfF ; _MATELM1( 1 ,0) -= _term; _MATELM1( 0 ,0) += _term; /*REACTION*/ /* ~ RA2fMg <-> RA2Mg ( kfB , kfF )*/ _term = kfB ; _MATELM1( 3 ,3) += _term; _MATELM1( 6 ,3) -= _term; _term = kfF ; _MATELM1( 3 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2sMg <-> RA2Mg ( ksB , ksF )*/ _term = ksB ; _MATELM1( 0 ,0) += _term; _MATELM1( 6 ,0) -= _term; _term = ksF ; _MATELM1( 0 ,6) -= _term; _MATELM1( 6 ,6) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d1Mg ( kd1B , kd1F )*/ _term = kd1B ; _MATELM1( 6 ,6) += _term; _MATELM1( 5 ,6) -= _term; _term = kd1F ; _MATELM1( 6 ,5) -= _term; _MATELM1( 5 ,5) += _term; /*REACTION*/ /* ~ RA2Mg <-> RA2d2Mg ( kd2B , kd2F )*/ _term = kd2B ; _MATELM1( 6 ,6) += _term; _MATELM1( 4 ,6) -= _term; _term = kd2F ; _MATELM1( 6 ,4) -= _term; _MATELM1( 4 ,4) += _term; /*REACTION*/ /* ~ RA2Mg <-> RAMg ( ( 2.0 * koff ) , ( kon * T ) )*/ _term = ( 2.0 * koff ) ; _MATELM1( 6 ,6) += _term; _MATELM1( 7 ,6) -= _term; _term = ( kon * T ) ; _MATELM1( 6 ,7) -= _term; _MATELM1( 7 ,7) += _term; /*REACTION*/ /* ~ RAMg <-> RMg ( koff , ( 2.0 * kon * T ) )*/ _term = koff ; _MATELM1( 7 ,7) += _term; _MATELM1( 8 ,7) -= _term; _term = ( 2.0 * kon * T ) ; _MATELM1( 7 ,8) -= _term; _MATELM1( 8 ,8) += _term; /*REACTION*/ /* R + RA + RA2 + RA2d1 + RA2d2 + RA2f + RA2s + O + OMg + RMg + RAMg + RA2Mg + RA2d1Mg + RA2d2Mg + RA2fMg + RA2sMg = 1.0 */ /*CONSERVATION*/ } return _reset; } /*CVODE end*/ static void _thread_mem_init(ThreadDatum* _thread) { if (_thread1data_inuse) {_thread[_gth]._pval = (double*)ecalloc(6, sizeof(double)); }else{ _thread[_gth]._pval = _thread1data; _thread1data_inuse = 1; } } static void _thread_cleanup(ThreadDatum* _thread) { _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_cvspth1]._pvoid); _nrn_destroy_sparseobj_thread((SparseObj*)_thread[_spth1]._pvoid); if (_thread[_gth]._pval == _thread1data) { _thread1data_inuse = 0; }else{ free((void*)_thread[_gth]._pval); } } static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ Memb_list* _ml = _nt->_ml_list[_mechtype]; OMg = OMg0; O = O0; RA2sMg = RA2sMg0; RA2fMg = RA2fMg0; RA2d2Mg = RA2d2Mg0; RA2d1Mg = RA2d1Mg0; RA2Mg = RA2Mg0; RAMg = RAMg0; RMg = RMg0; RA2s = RA2s0; RA2f = RA2f0; RA2d2 = RA2d20; RA2d1 = RA2d10; RA2 = RA20; RA = RA0; R = R0; { T = 0.0 ; synon = 0.0 ; tRel = 0.0 ; R = 1.0 ; rates ( _threadargscomma_ v , t ) ; #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, 0, _ppvar[1*_STRIDE], t + 590.0 , 1.0 ); #else net_send ( _tqitem, -1, (Point_process*) _nt->_vdata[_ppvar[1*_STRIDE]], t + 590.0 , 1.0 ) ; #endif } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #pragma acc update device (_mechtype) if(_nt->compute_gpu) if (!_thread[_spth1]._pvoid) { _thread[_spth1]._pvoid = nrn_cons_sparseobj(kstates_NMDA16_2{}, 16, _ml, _threadargs_); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_so = (void*) acc_deviceptr(_thread[_spth1]._pvoid); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[_spth1]._pvoid), &_d_so, sizeof(void*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _tsav = -1e20; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V nao = _ion_nao; initmodel(_threadargs_); } } #if NET_RECEIVE_BUFFERING NetSendBuffer_t* _nsb = _ml->_net_send_buffer; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc wait(stream_id) #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu) update_net_send_buffer_on_host(_nt, _nsb); #endif {int _i; for (_i=0; _i < _nsb->_cnt; ++_i) { net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i], _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i], _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]); }} _nsb->_cnt = 0; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update device(_nsb->_cnt) if(_nt->compute_gpu) #endif #endif } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { g = w * gmax * O ; i = g * ( v - Erev ) ; } _current += i; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; double * _vec_shadow_rhs = _nt->_shadow_rhs; double * _vec_shadow_d = _nt->_shadow_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V nao = _ion_nao; _g = _nrn_current(_threadargs_, _v + .001); { _rhs = _nrn_current(_threadargs_, _v); } _g = (_g - _rhs)/.001; double _mfact = 1.e2/(_nd_area); _g *= _mfact; _rhs *= _mfact; _PRCELLSTATE_G #ifdef _OPENACC if(_nt->compute_gpu) { #pragma acc atomic update _vec_rhs[_nd_idx] -= _rhs; #pragma acc atomic update _vec_d[_nd_idx] += _g; } else { _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; } #else _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; #endif } #ifdef _OPENACC if(!(_nt->compute_gpu)) { for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; } #else for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; #endif } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { nao = _ion_nao; { sparse_thread(static_cast(_thread[_spth1]._pvoid), 16, _slist1, _dlist1, &t, dt, kstates_NMDA16_2{}, _linmat1, _threadargs_); }}} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*16); _dlist1 = (int*)malloc(sizeof(int)*16); _slist1[0] = &(RA2sMg) - _p; _dlist1[0] = &(DRA2sMg) - _p; _slist1[1] = &(OMg) - _p; _dlist1[1] = &(DOMg) - _p; _slist1[2] = &(O) - _p; _dlist1[2] = &(DO) - _p; _slist1[3] = &(RA2fMg) - _p; _dlist1[3] = &(DRA2fMg) - _p; _slist1[4] = &(RA2d2Mg) - _p; _dlist1[4] = &(DRA2d2Mg) - _p; _slist1[5] = &(RA2d1Mg) - _p; _dlist1[5] = &(DRA2d1Mg) - _p; _slist1[6] = &(RA2Mg) - _p; _dlist1[6] = &(DRA2Mg) - _p; _slist1[7] = &(RAMg) - _p; _dlist1[7] = &(DRAMg) - _p; _slist1[8] = &(RMg) - _p; _dlist1[8] = &(DRMg) - _p; _slist1[9] = &(RA2s) - _p; _dlist1[9] = &(DRA2s) - _p; _slist1[10] = &(RA2f) - _p; _dlist1[10] = &(DRA2f) - _p; _slist1[11] = &(RA2d2) - _p; _dlist1[11] = &(DRA2d2) - _p; _slist1[12] = &(RA2d1) - _p; _dlist1[12] = &(DRA2d1) - _p; _slist1[13] = &(RA2) - _p; _dlist1[13] = &(DRA2) - _p; _slist1[14] = &(RA) - _p; _dlist1[14] = &(DRA) - _p; _slist1[15] = &(R) - _p; _dlist1[15] = &(DR) - _p; #pragma acc enter data copyin(_slist1[0:16]) #pragma acc enter data copyin(_dlist1[0:16]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/is.cpp000066400000000000000000000531001425457616700215750ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ , _thread[0:4] , _slist1[0:2], _dlist1[0:2] , _slist2[0:2] #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #define nrn_init _nrn_init__Is #define nrn_cur _nrn_cur__Is #define _nrn_current _nrn_current__Is #define nrn_jacob _nrn_jacob__Is #define nrn_state _nrn_state__Is #define initmodel initmodel__Is #define _net_receive _net_receive__Is #define _net_init _net_init__Is #define nrn_state_launcher nrn_state_Is_launcher #define nrn_cur_launcher nrn_cur_Is_launcher #define nrn_jacob_launcher nrn_jacob_Is_launcher #define rates rates_Is #define states states_Is #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define gsbar _p[0*_STRIDE] #define ica _p[1*_STRIDE] #define ics _p[2*_STRIDE] #define m _p[3*_STRIDE] #define n _p[4*_STRIDE] #define Dm _p[5*_STRIDE] #define Dn _p[6*_STRIDE] #define cai _p[7*_STRIDE] #define ins _p[8*_STRIDE] #define lca _p[9*_STRIDE] #define _v_unused _p[10*_STRIDE] #define _g_unused _p[11*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _ion_cai _nt_data[_ppvar[0*_STRIDE]] #define _ion_ica _nt_data[_ppvar[1*_STRIDE]] #define _ion_dicadv _nt_data[_ppvar[2*_STRIDE]] #define _ion_ics _nt_data[_ppvar[3*_STRIDE]] #define _ion_dicsdv _nt_data[_ppvar[4*_STRIDE]] #define _ion_ins _nt_data[_ppvar[5*_STRIDE]] #define _ion_dinsdv _nt_data[_ppvar[6*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ extern double celsius; #define _celsius_ _celsius__Is double _celsius_; #pragma acc declare copyin(_celsius_) #if 0 /*BBCORE*/ /* declaration of user functions */ static void _hoc_alp(void); static void _hoc_bet(void); static void _hoc_rates(void); #endif /*BBCORE*/ static int _mechtype; #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { "setdata_Is", _hoc_setdata, "alp_Is", _hoc_alp, "bet_Is", _hoc_bet, "rates_Is", _hoc_rates, 0, 0 }; #endif /*BBCORE*/ #define alp alp_Is #define bet bet_Is #pragma acc routine seq inline double alp( _threadargsprotocomma_ double , double ); #pragma acc routine seq inline double bet( _threadargsprotocomma_ double , double ); /* declare global and static user variables */ static int _thread1data_inuse = 0; static double _thread1data[4]; #define _gth 3 #define mtau_Is _thread1data[0] #define mtau _thread[_gth]._pval[0] #define minf_Is _thread1data[1] #define minf _thread[_gth]._pval[1] #define ntau_Is _thread1data[2] #define ntau _thread[_gth]._pval[2] #define ninf_Is _thread1data[3] #define ninf _thread[_gth]._pval[3] static void _acc_globals_update() { _celsius_ = celsius; #pragma acc update device(_celsius_) } #define celsius _celsius_ #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "gsbar_Is", 0, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "mtau_Is", "ms", "ntau_Is", "ms", "gsbar_Is", "S/cm2", "ica_Is", "mA/cm2", "ics_Is", "mA/cm2", 0,0 }; #endif /*BBCORE*/ static double delta_t = 0.01; #pragma acc declare copyin(delta_t) static double m0 = 0; #pragma acc declare copyin(m0) static double n0 = 0; #pragma acc declare copyin(n0) /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { "minf_Is", &minf_Is, "ninf_Is", &ninf_Is, "mtau_Is", &mtau_Is, "ntau_Is", &ntau_Is, 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "Is", "gsbar_Is", 0, "ica_Is", "ics_Is", 0, "m_Is", "n_Is", 0, 0}; static int _ca_type; static int _cs_type; static int _ns_type; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ gsbar = 5e-05; prop_ion = need_memb(_ca_sym); nrn_promote(prop_ion, 1, 0); _ppvar[0]._pval = &prop_ion->param[1]; /* cai */ _ppvar[1]._pval = &prop_ion->param[3]; /* ica */ _ppvar[2]._pval = &prop_ion->param[4]; /* _ion_dicadv */ prop_ion = need_memb(_cs_sym); _ppvar[3]._pval = &prop_ion->param[3]; /* ics */ _ppvar[4]._pval = &prop_ion->param[4]; /* _ion_dicsdv */ prop_ion = need_memb(_ns_sym); _ppvar[5]._pval = &prop_ion->param[3]; /* ins */ _ppvar[6]._pval = &prop_ion->param[4]; /* _ion_dinsdv */ #endif /* BBCORE */ } static void _initlists(); static void _thread_mem_init(ThreadDatum*); static void _thread_cleanup(ThreadDatum*); static void _update_ion_pointer(Datum*); #define _psize 12 #define _ppsize 7 void _is_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); _ca_type = nrn_get_mechtype("ca_ion"); _cs_type = nrn_get_mechtype("cs_ion"); _ns_type = nrn_get_mechtype("ns_ion"); #if 0 /*BBCORE*/ ion_reg("ca", -10000.); ion_reg("cs", 2.0); ion_reg("ns", 2.0); _ca_sym = hoc_lookup("ca_ion"); _cs_sym = hoc_lookup("cs_ion"); _ns_sym = hoc_lookup("ns_ion"); #endif /*BBCORE*/ register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, 5); _extcall_thread = (ThreadDatum*)ecalloc(4, sizeof(ThreadDatum)); _thread_mem_init(_extcall_thread); _thread1data_inuse = 0; _nrn_thread_reg1(_mechtype, _thread_mem_init); _nrn_thread_reg0(_mechtype, _thread_cleanup); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "ca_ion"); hoc_register_dparam_semantics(_mechtype, 1, "ca_ion"); hoc_register_dparam_semantics(_mechtype, 2, "ca_ion"); hoc_register_dparam_semantics(_mechtype, 3, "cs_ion"); hoc_register_dparam_semantics(_mechtype, 4, "cs_ion"); hoc_register_dparam_semantics(_mechtype, 5, "ns_ion"); hoc_register_dparam_semantics(_mechtype, 6, "ns_ion"); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = "Cardiac L-type Calcium channel"; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} static inline int rates(_threadargsprotocomma_ double); #define _deriv1_advance _thread[0]._i #define _dith1 1 #define _newtonspace1 _thread[2]._pvoid static int _ode_spec1(_threadargsproto_); /*static int _ode_matsol1(_threadargsproto_);*/ /* _derivimplicit_ states _Is */ #ifndef INSIDE_NMODL #define INSIDE_NMODL #endif struct _newton_states_Is { int operator()(_threadargsproto_) const; }; #define _slist2 _slist2_Is int* _slist2; #pragma acc declare create(_slist2) #define _slist1 _slist1_Is int* _slist1; #pragma acc declare create(_slist1) #define _dlist1 _dlist1_Is int* _dlist1; #pragma acc declare create(_dlist1) struct states_Is { int operator()(_threadargsproto_) const; }; /*CVODE*/ static int _ode_spec1 (_threadargsproto_) {int _reset = 0; { rates ( _threadargscomma_ v ) ; Dm = ( minf - m ) / mtau ; Dn = ( ninf - n ) / ntau ; } return _reset; } static int _ode_matsol1 (_threadargsproto_) { rates ( _threadargscomma_ v ) ; Dm = Dm / (1. - dt*( ( ( ( - 1.0 ) ) ) / mtau )) ; Dn = Dn / (1. - dt*( ( ( ( - 1.0 ) ) ) / ntau )) ; return 0; } /*END CVODE*/ int states ::operator()(_threadargsproto_) const { int _reset=0; int error = 0; { double* _savstate1 = (double*)_thread[_dith1]._pval; double* _dlist2 = (double*)(_thread[_dith1]._pval) + (2*_cntml_padded); {int _id; for(_id=0; _id < 2; _id++) { _savstate1[_id*_STRIDE] = _p[_slist1[_id]*_STRIDE];}} _reset = nrn_newton_thread(static_cast(_newtonspace1), 2, _slist2, _newton_states_Is{}, _dlist2, _threadargs_); /*if(_reset) {abort_run(_reset);}*/ } return _reset; } int _newton_states_Is::operator()(_threadargsproto_) const { int _reset=0; { double* _savstate1 = (double*)_thread[_dith1]._pval; double* _dlist2 = (double*)(_thread[_dith1]._pval) + (2*_cntml_padded); int _counte = -1; { rates ( _threadargscomma_ v ) ; Dm = ( minf - m ) / mtau ; Dn = ( ninf - n ) / ntau ; {int _id; for(_id=0; _id < 2; _id++) { if (_deriv1_advance) { _dlist2[(++_counte)*_STRIDE] = _p[_dlist1[_id]*_STRIDE] - (_p[_slist1[_id]*_STRIDE] - _savstate1[_id*_STRIDE])/dt; }else{ _dlist2[(++_counte)*_STRIDE] = _p[_slist1[_id]*_STRIDE] - _savstate1[_id*_STRIDE];}}} } } return _reset;} double alp ( _threadargsprotocomma_ double _lv , double _li ) { double _lalp; if ( _li == 0.0 ) { _lalp = 0.095 * exp ( - 0.01 * ( _lv - 5.0 ) ) / ( exp ( - 0.072 * ( _lv - 5.0 ) ) + 1.0 ) ; } else if ( _li == 1.0 ) { _lalp = 0.012 * exp ( - 0.008 * ( _lv + 28.0 ) ) / ( exp ( 0.15 * ( _lv + 28.0 ) ) + 1.0 ) ; } return _lalp; } #if 0 /*BBCORE*/ static void _hoc_alp(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = alp ( _threadargs_, *getarg(1) , *getarg(2) ; hoc_retpushx(_r); } #endif /*BBCORE*/ double bet ( _threadargsprotocomma_ double _lv , double _li ) { double _lbet; if ( _li == 0.0 ) { _lbet = 0.07 * exp ( - 0.017 * ( _lv + 44.0 ) ) / ( exp ( 0.05 * ( _lv + 44.0 ) ) + 1.0 ) ; } else if ( _li == 1.0 ) { _lbet = 0.0065 * exp ( - 0.02 * ( _lv + 30.0 ) ) / ( exp ( - 0.2 * ( _lv + 30.0 ) ) + 1.0 ) ; } return _lbet; } #if 0 /*BBCORE*/ static void _hoc_bet(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = bet ( _threadargs_, *getarg(1) , *getarg(2) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static int rates ( _threadargsprotocomma_ double _lv ) { double _la , _lb ; _la = alp ( _threadargscomma_ _lv , 0.0 ) ; _lb = bet ( _threadargscomma_ _lv , 0.0 ) ; mtau = 1.0 / ( _la + _lb ) ; minf = _la / ( _la + _lb ) ; _la = alp ( _threadargscomma_ _lv , 1.0 ) ; _lb = bet ( _threadargscomma_ _lv , 1.0 ) ; ntau = 1.0 / ( _la + _lb ) ; ninf = _la / ( _la + _lb ) ; return 0; } #if 0 /*BBCORE*/ static void _hoc_rates(void) { double _r; double* _p; Datum* _ppvar; ThreadDatum* _thread; NrnThread* _nt; if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; } _thread = _extcall_thread; _nt = nrn_threads; _r = 1.; rates ( _threadargs_, *getarg(1) ; hoc_retpushx(_r); } #endif /*BBCORE*/ static void _thread_mem_init(ThreadDatum* _thread) { _thread[_dith1]._pval = NULL; if (_thread1data_inuse) {_thread[_gth]._pval = (double*)ecalloc(4, sizeof(double)); }else{ _thread[_gth]._pval = _thread1data; _thread1data_inuse = 1; } } static void _thread_cleanup(ThreadDatum* _thread) { free( _thread[_dith1]._pval); nrn_destroy_newtonspace((NewtonSpace*) _newtonspace1); if (_thread[_gth]._pval == _thread1data) { _thread1data_inuse = 0; }else{ free((void*)_thread[_gth]._pval); } } static void _update_ion_pointer(Datum* _ppvar) { } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ m = m0; n = n0; { rates ( _threadargscomma_ v ) ; m = minf ; n = ninf ; } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; _deriv1_advance = 0; #ifdef _OPENACC #pragma acc update device (_deriv1_advance) if (_nt->compute_gpu) #endif if (!_newtonspace1) { _newtonspace1 = nrn_cons_newtonspace(2, _cntml_padded); _thread[_dith1]._pval = makevector(2*2*_cntml_padded*sizeof(double)); #ifdef _OPENACC if (_nt->compute_gpu) { void* _d_ns = (void*)acc_deviceptr(_newtonspace1); double* _d_pd = (double*)acc_copyin(_thread[_dith1]._pval,2*2*_cntml_padded* sizeof(double)); ThreadDatum* _d_td = (ThreadDatum*)acc_deviceptr(_thread); acc_memcpy_to_device(&(_d_td[2]._pvoid), &_d_ns, sizeof(void*)); acc_memcpy_to_device(&(_d_td[_dith1]._pval), &_d_pd, sizeof(double*)); } #endif } _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V cai = _ion_cai; initmodel(_threadargs_); } } _deriv1_advance = 1; #ifdef _OPENACC #pragma acc update device (_deriv1_advance) if (_nt->compute_gpu) #endif } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { double _lEs ; _lEs = - 82.3 - 13.0287 * log ( cai ) ; ics = gsbar * m * n * ( v - _lEs ) ; ica = ics ; ins = - ics ; } _current += ica; _current += ics; _current += ins; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V cai = _ion_cai; _g = _nrn_current(_threadargs_, _v + .001); { double _dins; double _dics; double _dica; _dica = ica; _dics = ics; _dins = ins; _rhs = _nrn_current(_threadargs_, _v); _ion_dicadv += (_dica - ica)/.001 ; _ion_dicsdv += (_dics - ics)/.001 ; _ion_dinsdv += (_dins - ins)/.001 ; } _g = (_g - _rhs)/.001; _ion_ica += ica ; _ion_ics += ics ; _ion_ins += ins ; _PRCELLSTATE_G _vec_rhs[_nd_idx] -= _rhs; _vec_d[_nd_idx] += _g; } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v, _v = 0.0; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_state_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_STATE_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v=_v; { cai = _ion_cai; { derivimplicit_thread(2, _slist1, _dlist1, states_Is{}, _threadargs_); } }} } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _slist1 = (int*)malloc(sizeof(int)*2); _dlist1 = (int*)malloc(sizeof(int)*2); _slist1[0] = &(m) - _p; _dlist1[0] = &(Dm) - _p; _slist1[1] = &(n) - _p; _dlist1[1] = &(Dn) - _p; #pragma acc enter data copyin(_slist1[0:2]) #pragma acc enter data copyin(_dlist1[0:2]) _slist2 = (int*)malloc(sizeof(int)*2); _slist2[0] = &(m) - _p; _slist2[1] = &(n) - _p; #pragma acc enter data copyin(_slist2[0:2]) _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/cpp/isi.cpp000066400000000000000000000000001425457616700217350ustar00rootroot00000000000000mod2c-8.2.2/test/validation/mod2c_core/cpp/zoidsyn.cpp000066400000000000000000000502151425457616700226650ustar00rootroot00000000000000/* Created by Language version: 6.2.0 */ /* VECTORIZED */ #include #include #include #undef PI #include "coreneuron/utils/randoms/nrnran123.h" #include "coreneuron/nrnoc/md1redef.h" #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/ivocvect.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/gpu/nrn_acc_manager.hpp" #include "coreneuron/sim/scopmath/newton_struct.h" #include "coreneuron/sim/scopmath/newton_thread.hpp" #include "coreneuron/sim/scopmath/sparse_thread.hpp" #include "coreneuron/sim/scopmath/ssimplic_thread.hpp" #include "coreneuron/nrnoc/md2redef.h" #include "coreneuron/mechanism/register_mech.hpp" #if !NRNGPU #if !defined(DISABLE_HOC_EXP) #undef exp #define exp hoc_Exp #endif #endif namespace coreneuron { #define _thread_present_ /**/ #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #include #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], nrn_ion_global_map[0:nrn_ion_global_map_size][0:ion_global_map_member_size], _nt[0:1] _thread_present_) if(_nt->compute_gpu)") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _nt[0:1], _ml[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1] _thread_present_) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("acc parallel loop present(_ni[0:_cntml_actual], _nt_data[0:_nt->_ndata], _p[0:_cntml_padded*_psize], _ppvar[0:_cntml_padded*_ppsize], _vec_v[0:_nt->end], _vec_shadow_rhs[0:_nt->shadow_rhs_cnt], _vec_shadow_d[0:_nt->shadow_rhs_cnt], _vec_d[0:_nt->end], _vec_rhs[0:_nt->end], _nt[0:1]) if(_nt->compute_gpu) async(stream_id)") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("acc parallel loop present(_pnt[0:_pnt_length], _nrb[0:1], _nt[0:1], nrn_threads[0:nrn_nthread]) if(_nt->compute_gpu) async(stream_id)") #else #define _PRAGMA_FOR_INIT_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_STATE_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ _Pragma("") #define _PRAGMA_FOR_NETRECV_ACC_LOOP_ _Pragma("") #endif #if defined(__ICC) || defined(__INTEL_COMPILER) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ivdep") #elif defined(__IBMC__) || defined(__IBMCPP__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("ibm independent_loop") #elif defined(__PGI) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("vector") #elif defined(_CRAYC) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("_CRI ivdep") #elif defined(__clang__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("clang loop vectorize(enable)") #elif defined(__GNUC__) || defined(__GNUG__) #define _PRAGMA_FOR_VECTOR_LOOP_ _Pragma("GCC ivdep") #else #define _PRAGMA_FOR_VECTOR_LOOP_ #endif // _PRAGMA_FOR_VECTOR_LOOP_ #if !defined(LAYOUT) /* 1 means AoS, >1 means AoSoA, <= 0 means SOA */ #define LAYOUT 1 #endif #if LAYOUT >= 1 #define _STRIDE LAYOUT #else #define _STRIDE _cntml_padded + _iml #endif #if !defined(NET_RECEIVE_BUFFERING) #define NET_RECEIVE_BUFFERING 1 #endif #define nrn_init _nrn_init__ZoidSyn #define nrn_cur _nrn_cur__ZoidSyn #define _nrn_current _nrn_current__ZoidSyn #define nrn_jacob _nrn_jacob__ZoidSyn #define nrn_state _nrn_state__ZoidSyn #define initmodel initmodel__ZoidSyn #define _net_receive _net_receive__ZoidSyn #define _net_init _net_init__ZoidSyn #define nrn_state_launcher nrn_state_ZoidSyn_launcher #define nrn_cur_launcher nrn_cur_ZoidSyn_launcher #define nrn_jacob_launcher nrn_jacob_ZoidSyn_launcher #if NET_RECEIVE_BUFFERING #define _net_buf_receive _net_buf_receive_ZoidSyn void _net_buf_receive(NrnThread*); #endif #undef _threadargscomma_ #undef _threadargsprotocomma_ #undef _threadargs_ #undef _threadargsproto_ #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v, #define _threadargsprotocomma_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v, #define _threadargs_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, v #define _threadargsproto_ int _iml, int _cntml_padded, double* _p, Datum* _ppvar, ThreadDatum* _thread, NrnThread* _nt, double v /*SUPPRESS 761*/ /*SUPPRESS 762*/ /*SUPPRESS 763*/ /*SUPPRESS 765*/ /* Thread safe. No static _p or _ppvar. */ #define t _nt->_t #define dt _nt->_dt #define trf _p[0*_STRIDE] #define tp _p[1*_STRIDE] #define start _p[2*_STRIDE] #define interval _p[3*_STRIDE] #define number _p[4*_STRIDE] #define e _p[5*_STRIDE] #define gmax _p[6*_STRIDE] #define i _p[7*_STRIDE] #define g _p[8*_STRIDE] #define on _p[9*_STRIDE] #define tally _p[10*_STRIDE] #define m _p[11*_STRIDE] #define b _p[12*_STRIDE] #define dur _p[13*_STRIDE] #define t0 _p[14*_STRIDE] #define _v_unused _p[15*_STRIDE] #define _g_unused _p[16*_STRIDE] #define _tsav _p[17*_STRIDE] #ifndef NRN_PRCELLSTATE #define NRN_PRCELLSTATE 0 #endif #if NRN_PRCELLSTATE #define _PRCELLSTATE_V _v_unused = _v; #define _PRCELLSTATE_G _g_unused = _g; #else #define _PRCELLSTATE_V /**/ #define _PRCELLSTATE_G /**/ #endif #define _nd_area _nt_data[_ppvar[0*_STRIDE]] #if MAC #if !defined(v) #define v _mlhv #endif #if !defined(h) #define h _mlhh #endif #endif static int hoc_nrnpointerindex = -1; static ThreadDatum* _extcall_thread; /* external NEURON variables */ #if 0 /*BBCORE*/ /* declaration of user functions */ #endif /*BBCORE*/ #define _mechtype _mechtype_ZoidSyn int _mechtype; #pragma acc declare copyin (_mechtype) static int _pointtype; #if 0 /*BBCORE*/ static void* _hoc_create_pnt(_ho) Object* _ho; { void* create_point_process(); return create_point_process(_pointtype, _ho); } static void _hoc_destroy_pnt(); static double _hoc_loc_pnt(_vptr) void* _vptr; {double loc_point_process(); return loc_point_process(_pointtype, _vptr); } static double _hoc_has_loc(_vptr) void* _vptr; {double has_loc_point(); return has_loc_point(_vptr); } static double _hoc_get_loc_pnt(_vptr)void* _vptr; { double get_loc_point_process(); return (get_loc_point_process(_vptr)); } #endif /*BBCORE*/ #if 0 /*BBCORE*/ /* connect user functions to hoc names */ static VoidFunc hoc_intfunc[] = { 0,0 }; static Member_func _member_func[] = { "loc", _hoc_loc_pnt, "has_loc", _hoc_has_loc, "get_loc", _hoc_get_loc_pnt, 0, 0 }; #endif /*BBCORE*/ /* declare global and static user variables */ static void _acc_globals_update() { } #if 0 /*BBCORE*/ /* some parameters have upper and lower limits */ static HocParmLimits _hoc_parm_limits[] = { "gmax", 0, 1e+09, "interval", 0, 1e+09, "start", 0, 1e+09, "tp", 0, 1e+09, "trf", 0, 1e+09, 0,0,0 }; static HocParmUnits _hoc_parm_units[] = { "trf", "ms", "tp", "ms", "start", "ms", "interval", "ms", "e", "mV", "gmax", "nS", "i", "nA", "g", "nS", 0,0 }; #endif /*BBCORE*/ /* connect global user variables to hoc */ static DoubScal hoc_scdoub[] = { 0,0 }; static DoubVec hoc_vdoub[] = { 0,0,0 }; static double _sav_indep; static void nrn_alloc(double*, Datum*, int); void nrn_init(NrnThread*, Memb_list*, int); void nrn_state(NrnThread*, Memb_list*, int); void nrn_cur(NrnThread*, Memb_list*, int); #if 0 /*BBCORE*/ static void _hoc_destroy_pnt(_vptr) void* _vptr; { destroy_point_process(_vptr); } #endif /*BBCORE*/ /* connect range variables in _p that hoc is supposed to know about */ static const char *_mechanism[] = { "6.2.0", "ZoidSyn", "trf", "tp", "start", "interval", "number", "e", "gmax", 0, "i", "g", 0, 0, 0}; static void nrn_alloc(double* _p, Datum* _ppvar, int _type) { #if 0 /*BBCORE*/ /*initialize range parameters*/ trf = 0; tp = 0; start = 0; interval = 0; number = 0; e = 0; gmax = 0; #endif /* BBCORE */ } static void _initlists(); #define _tqitem &(_nt->_vdata[_ppvar[2*_STRIDE]]) #if NET_RECEIVE_BUFFERING #undef _tqitem #define _tqitem _ppvar[2*_STRIDE] #endif void _net_receive(Point_process*, int, double); #define _psize 18 #define _ppsize 3 void _zoidsyn_reg() { int _vectorized = 1; _initlists(); _mechtype = nrn_get_mechtype(_mechanism[1]); if (_mechtype == -1) return; _nrn_layout_reg(_mechtype, LAYOUT); #if 0 /*BBCORE*/ #endif /*BBCORE*/ _pointtype = point_register_mech(_mechanism, nrn_alloc,nrn_cur, NULL, nrn_state, nrn_init, hoc_nrnpointerindex, NULL/*_hoc_create_pnt*/, NULL/*_hoc_destroy_pnt*/, /*_member_func,*/ 1); hoc_register_prop_size(_mechtype, _psize, _ppsize); hoc_register_dparam_semantics(_mechtype, 0, "area"); hoc_register_dparam_semantics(_mechtype, 1, "pntproc"); hoc_register_dparam_semantics(_mechtype, 2, "netsend"); #if NET_RECEIVE_BUFFERING hoc_register_net_receive_buffering(_net_buf_receive, _mechtype); #endif #if NET_RECEIVE_BUFFERING hoc_register_net_send_buffering(_mechtype); #endif set_pnt_receive(_mechtype, _net_receive, nullptr, 1); hoc_register_var(hoc_scdoub, hoc_vdoub, NULL); } static const char *modelname = ""; static int error; static int _ninits = 0; static int _match_recurse=1; static void _modl_cleanup(){ _match_recurse=1;} #if NET_RECEIVE_BUFFERING #undef t #define t _nrb_t static inline void _net_receive_kernel(double, Point_process*, int _weight_index, double _flag); void _net_buf_receive(NrnThread* _nt) { if (!_nt->_ml_list) { return; } Memb_list* _ml = _nt->_ml_list[_mechtype]; if (!_ml) { return; } NetReceiveBuffer_t* _nrb = _ml->_net_receive_buffer; int _di; int stream_id = _nt->stream_id; Point_process* _pnt = _nt->pntprocs; int _pnt_length = _nt->n_pntproc - _nrb->_pnt_offset; int _displ_cnt = _nrb->_displ_cnt; _PRAGMA_FOR_NETRECV_ACC_LOOP_ for (_di = 0; _di < _displ_cnt; ++_di) { int _inrb; int _di0 = _nrb->_displ[_di]; int _di1 = _nrb->_displ[_di + 1]; for (_inrb = _di0; _inrb < _di1; ++_inrb) { int _i = _nrb->_nrb_index[_inrb]; int _j = _nrb->_pnt_index[_i]; int _k = _nrb->_weight_index[_i]; double _nrt = _nrb->_nrb_t[_i]; double _nrflag = _nrb->_nrb_flag[_i]; _net_receive_kernel(_nrt, _pnt + _j, _k, _nrflag); } } #pragma acc wait(stream_id) _nrb->_displ_cnt = 0; _nrb->_cnt = 0; /*printf("_net_buf_receive__ZoidSyn %d\n", _nt->_id);*/ { NetSendBuffer_t* _nsb = _ml->_net_send_buffer; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu) update_net_send_buffer_on_host(_nt, _nsb); #endif int _i; for (_i=0; _i < _nsb->_cnt; ++_i) { net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i], _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i], _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]); } _nsb->_cnt = 0; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update device(_nsb->_cnt) if (_nt->compute_gpu) #endif } } static void _net_send_buffering(NetSendBuffer_t* _nsb, int _sendtype, int _i_vdata, int _weight_index, int _ipnt, double _t, double _flag) { int _i = 0; #pragma acc atomic capture _i = _nsb->_cnt++; #if !defined(_OPENACC) if (_i >= _nsb->_size) { _nsb->grow(); } #endif if (_i < _nsb->_size) { _nsb->_sendtype[_i] = _sendtype; _nsb->_vdata_index[_i] = _i_vdata; _nsb->_weight_index[_i] = _weight_index; _nsb->_pnt_index[_i] = _ipnt; _nsb->_nsb_t[_i] = _t; _nsb->_nsb_flag[_i] = _flag; } } void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) { NrnThread* _nt = nrn_threads + _pnt->_tid; NetReceiveBuffer_t* _nrb = _nt->_ml_list[_mechtype]->_net_receive_buffer; if (_nrb->_cnt >= _nrb->_size){ realloc_net_receive_buffer(_nt, _nt->_ml_list[_mechtype]); } _nrb->_pnt_index[_nrb->_cnt] = _pnt - _nt->pntprocs; _nrb->_weight_index[_nrb->_cnt] = _weight_index; _nrb->_nrb_t[_nrb->_cnt] = _nt->_t; _nrb->_nrb_flag[_nrb->_cnt] = _lflag; ++_nrb->_cnt; } static void _net_receive_kernel(double _nrb_t, Point_process* _pnt, int _weight_index, double _lflag) #else void _net_receive (Point_process* _pnt, int _weight_index, double _lflag) #endif { double* _p; Datum* _ppvar; ThreadDatum* _thread; double v = 0; Memb_list* _ml; int _cntml_padded, _cntml_actual; int _iml; double* _args; NrnThread* _nt; int _tid = _pnt->_tid; _nt = nrn_threads + _tid; _thread = (ThreadDatum*)0; double *_weights = _nt->_weights; _args = _weights + _weight_index; _ml = _nt->_ml_list[_pnt->_type]; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _iml = _pnt->_i_instance; #if LAYOUT == 1 /*AoS*/ _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #endif #if LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; #endif #if LAYOUT > 1 /*AoSoA*/ #error AoSoA not implemented. #endif #if !defined(_OPENACC) assert(_tsav <= t); #endif _tsav = t; #if !NET_RECEIVE_BUFFERING if (_lflag == 1. ) {*(_tqitem) = 0;} #endif { if ( ( on == 0.0 ) && ( _lflag == 1.0 ) ) { t0 = t ; m = 1.0 / trf ; b = 0.0 ; on = 1.0 ; #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, _weight_index, _ppvar[1*_STRIDE], t + trf , 2.0 ); #else net_send ( _tqitem, _weight_index, _pnt, t + trf , 2.0 ) ; #endif } if ( _lflag == 2.0 ) { m = 0.0 ; b = 1.0 ; #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, _weight_index, _ppvar[1*_STRIDE], t + tp , 3.0 ); #else net_send ( _tqitem, _weight_index, _pnt, t + tp , 3.0 ) ; #endif } if ( _lflag == 3.0 ) { t0 = t ; m = - 1.0 / trf ; b = 1.0 ; #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, _weight_index, _ppvar[1*_STRIDE], t + trf , 4.0 ); #else net_send ( _tqitem, _weight_index, _pnt, t + trf , 4.0 ) ; #endif } if ( _lflag == 4.0 ) { m = 0.0 ; b = 0.0 ; on = 0.0 ; if ( tally > 0.0 ) { #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, _weight_index, _ppvar[1*_STRIDE], t + interval - dur , 1.0 ); #else net_send ( _tqitem, _weight_index, _pnt, t + interval - dur , 1.0 ) ; #endif tally = tally - 1.0 ; } } } #if NET_RECEIVE_BUFFERING #undef t #define t _nt->_t #endif } static inline void initmodel(_threadargsproto_) { int _i; double _save;{ Memb_list* _ml = _nt->_ml_list[_mechtype]; { if ( trf <= 0.0 ) { trf = 1.0 ; printf ( "trf must be longer than 0\n" ) ; printf ( "trf has been increased to %g ms\n" , trf ) ; } if ( tp < 0.0 ) { tp = 0.0 ; printf ( "tp must not be negative\n" ) ; printf ( "tp has been changed to %g ms\n" , tp ) ; } dur = 2.0 * trf + tp ; if ( interval <= dur ) { interval = dur + 1.0 ; printf ( "interval must be longer than trapezoid duration\n" ) ; printf ( "interval has been increased to %g ms\n" , interval ) ; } on = 0.0 ; m = 0.0 ; b = 0.0 ; tally = number ; if ( tally > 0.0 ) { #if NET_RECEIVE_BUFFERING _net_send_buffering(_ml->_net_send_buffer, 0, _tqitem, 0, _ppvar[1*_STRIDE], t + start , 1.0 ); #else net_send ( _tqitem, -1, (Point_process*) _nt->_vdata[_ppvar[1*_STRIDE]], t + start , 1.0 ) ; #endif tally = tally - 1.0 ; } } } } void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){ double* _p; Datum* _ppvar; ThreadDatum* _thread; double _v, v; int* _ni; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; #pragma acc update device (_mechtype) if(_nt->compute_gpu) _acc_globals_update(); double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; if (_nrn_skip_initmodel == 0) { #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_INIT_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _tsav = -1e20; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V v = _v; _PRCELLSTATE_V initmodel(_threadargs_); } } #if NET_RECEIVE_BUFFERING NetSendBuffer_t* _nsb = _ml->_net_send_buffer; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc wait(stream_id) #pragma acc update self(_nsb->_cnt) if(_nt->compute_gpu) update_net_send_buffer_on_host(_nt, _nsb); #endif {int _i; for (_i=0; _i < _nsb->_cnt; ++_i) { net_sem_from_gpu(_nsb->_sendtype[_i], _nsb->_vdata_index[_i], _nsb->_weight_index[_i], _nt->_id, _nsb->_pnt_index[_i], _nsb->_nsb_t[_i], _nsb->_nsb_flag[_i]); }} _nsb->_cnt = 0; #if defined(_OPENACC) && !defined(DISABLE_OPENACC) #pragma acc update device(_nsb->_cnt) if(_nt->compute_gpu) #endif #endif } static double _nrn_current(_threadargsproto_, double _v){double _current=0.;v=_v;{ { g = gmax * ( m * ( t - t0 ) + b ) ; i = ( 0.001 ) * g * ( v - e ) ; } _current += i; } return _current; } #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) void nrn_state_launcher(NrnThread*, Memb_list*, int, int); void nrn_jacob_launcher(NrnThread*, Memb_list*, int, int); void nrn_cur_launcher(NrnThread*, Memb_list*, int, int); #endif void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; ThreadDatum* _thread; int* _ni; double _rhs, _g, _v, v; int _iml, _cntml_padded, _cntml_actual; _ni = _ml->_nodeindices; _cntml_actual = _ml->_nodecount; _cntml_padded = _ml->_nodecount_padded; _thread = _ml->_thread; double * _vec_rhs = _nt->_actual_rhs; double * _vec_d = _nt->_actual_d; double * _vec_shadow_rhs = _nt->_shadow_rhs; double * _vec_shadow_d = _nt->_shadow_d; #if defined(ENABLE_CUDA_INTERFACE) && defined(_OPENACC) && !defined(DISABLE_OPENACC) NrnThread* d_nt = acc_deviceptr(_nt); Memb_list* d_ml = acc_deviceptr(_ml); nrn_cur_launcher(d_nt, d_ml, _type, _cntml_actual); return; #endif double * _nt_data = _nt->_data; double * _vec_v = _nt->_actual_v; int stream_id = _nt->stream_id; #if LAYOUT == 1 /*AoS*/ for (_iml = 0; _iml < _cntml_actual; ++_iml) { _p = _ml->_data + _iml*_psize; _ppvar = _ml->_pdata + _iml*_ppsize; #elif LAYOUT == 0 /*SoA*/ _p = _ml->_data; _ppvar = _ml->_pdata; /* insert compiler dependent ivdep like pragma */ _PRAGMA_FOR_VECTOR_LOOP_ _PRAGMA_FOR_CUR_SYN_ACC_LOOP_ for (_iml = 0; _iml < _cntml_actual; ++_iml) { #else /* LAYOUT > 1 */ /*AoSoA*/ #error AoSoA not implemented. for (;;) { /* help clang-format properly indent */ #endif int _nd_idx = _ni[_iml]; _v = _vec_v[_nd_idx]; _PRCELLSTATE_V _g = _nrn_current(_threadargs_, _v + .001); { _rhs = _nrn_current(_threadargs_, _v); } _g = (_g - _rhs)/.001; double _mfact = 1.e2/(_nd_area); _g *= _mfact; _rhs *= _mfact; _PRCELLSTATE_G #ifdef _OPENACC if(_nt->compute_gpu) { #pragma acc atomic update _vec_rhs[_nd_idx] -= _rhs; #pragma acc atomic update _vec_d[_nd_idx] += _g; } else { _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; } #else _vec_shadow_rhs[_iml] = _rhs; _vec_shadow_d[_iml] = _g; #endif } #ifdef _OPENACC if(!(_nt->compute_gpu)) { for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; } #else for (_iml = 0; _iml < _cntml_actual; ++_iml) { int _nd_idx = _ni[_iml]; _vec_rhs[_nd_idx] -= _vec_shadow_rhs[_iml]; _vec_d[_nd_idx] += _vec_shadow_d[_iml]; #endif } } void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) { } static void terminal(){} static void _initlists(){ double _x; double* _p = &_x; int _i; static int _first = 1; int _cntml_actual=1; int _cntml_padded=1; int _iml=0; if (!_first) return; _first = 0; } } // namespace coreneuron_lib mod2c-8.2.2/test/validation/mod2c_core/mod000077700000000000000000000000001425457616700213072../modustar00rootroot00000000000000mod2c-8.2.2/test/validation/test_mod2c.in000077500000000000000000000020211425457616700202520ustar00rootroot00000000000000#!/bin/sh # usage: test_mod2c MOD2C MODFILE CFILE if [ $# -ne 3 ]; then echo 'usage: test_mod2c MOD2C MODFILE CFILE' >&2 exit 1 fi mod2c="$1" modinput="$2" cmpfile="$3" # mod2c writes to the directory in which it finds # the MOD file, so make a temporary directory for # this purpose. tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) function cleanup { if [ -d "$tmpdir" ]; then rm -r "$tmpdir" fi } trap cleanup EXIT function realpath { echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")" } cp "$modinput" "$tmpdir" modpfx=$(basename "$modinput" .mod) # canonicalize output @MOD2CFILTER@ < "$cmpfile" > "$tmpdir/_check" mod2c="$(realpath "$mod2c")" ( cd "$tmpdir"; "$mod2c" "$modpfx" ) if [ ! -e "$tmpdir/$modpfx".cpp ]; then echo "no output file generated" >&2 exit 2 fi @MOD2CFILTER@ < "$tmpdir/$modpfx".cpp > "$tmpdir/_out" ntok=$(wc -l < "$tmpdir/_out") echo "comparing $ntok tokens:" if diff "$tmpdir/_out" "$tmpdir/_check"; then echo "ok" exit 0 else echo "mismatch" exit 3 fi