{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### NMODL NONLINEAR solver\n", "\n", "`NONLINEAR` blocks contain a set of non-linear simultaneous equations. They can be directly specified by the user in the MOD file, or more commonly can be constructed from `KINETIC` or `DERIVATIVE` blocks by the `KineticBlock` and `SympySolver` visitors.\n", "\n", "These equations are rewritten in the form\n", "\n", "$$\n", "F(X) = 0,\n", "$$\n", "\n", "where $X$ is a vector containing the state variables involved in the equations, and this equation is then solved at runtime using [Newton's method](https://en.wikipedia.org/wiki/Newton%27s_method#k_variables,_k_functions)\n", "\n", "This is an iterative method: given an approximate solution $X^{(n)}$, a better approximation is given by\n", "\n", "$$\n", "X^{(n+1)} = X^{(n)} - J(X^{(n)})^{-1} F(X^{(n)})\n", "$$\n", "\n", "where $J(X) = \\frac{\\partial F(X)_i}{\\partial X_j}$ is the Jacobian of $F$.\n", "\n", "#### Newton solver\n", "\n", "$F$ and $J$ are constructed by the [solve_non_lin_system](https://github.com/BlueBrain/nmodl/blob/master/nmodl/ode.py#L209) python routine which uses SymPy to analytically differentiate $F$ to find the exact Jacobian at compile time. The initial approximate solution $X_0$ is chosen to simply be the current values of the state variables: as long as $dt$ is not too large the solution at $t+dt$ should not lie too far away.\n", "\n", "The iterative Newton solver is called `newton_solver` and is implemented in [src/solver/newton](https://github.com/BlueBrain/nmodl/blob/master/src/solver/newton/newton.hpp#L33) using the Eigen header-only matrix algebra library. Unit tests are available in [test/newton/newton.cpp](https://github.com/BlueBrain/nmodl/blob/master/test/newton/newton.cpp) with the tags \"`[analytic][solver]`\".\n", "\n", "#### Fall-back solver\n", "\n", "A fall-back solution if the analytic Jacobian is not available (for example if the equations use some custom neuron function calls that SymPy doesn't know how to differentiate, or if `VERBATIM` blocks are used within the `NONLINEAR` block) is to use the `newton_numerical_diff_solver` variant of this solver that uses a finite difference approximation to estimate the Jacobian numerically.\n", "\n", "This solver is also implemented in [src/solver/newton](https://github.com/BlueBrain/nmodl/blob/master/src/solver/newton/newton.hpp#L33), with Unit tests in [test/newton/newton.cpp](https://github.com/BlueBrain/nmodl/blob/master/test/newton/newton.cpp) with the tags \"`[numerical][solver]`\".\n", "\n", "**NB: this solver is implemented, but the visitor to set up the solve is not yet implemented**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" } }, "nbformat": 4, "nbformat_minor": 2 }