NEURON
nrndae.h
Go to the documentation of this file.
1 /**
2  * @file nrndae.h
3  * @brief Supports modifying voltage equations and adding new equations.
4  * @author Michael Hines, Robert McDougal
5  *
6  * @remark Subclasses of NrnDAE can work with equations of the form
7  * \f[$C \frac{dy}{dt} = f(y)$\f]. LinearModelAddition, defined in linmod.h
8  * and linmod.cpp is an example that supports linear dynamics of the
9  * form \f[$C \frac{dy}{dt} = A y + b$\f].
10  */
11 
12 #pragma once
13 #include "ivocvect.h"
14 #include "matrixmap.h"
15 
17 
18 #include <list>
19 #include <vector>
20 
21 /**
22  * NEURON Differential Algebraic Equations.
23  *
24  * @remark This is an abstract class; subclass this (or use a subclass) to
25  * add dynamics. LinearModelAddition is an example. See linmod.h.
26  */
27 class NrnDAE {
28  public:
29  /**
30  * Find the number of state variables introduced by this object.
31  *
32  * @return The number of states added (not modified) by this instance.
33  */
34  int extra_eqn_count();
35 
36  /**
37  * Allocate space for these dynamics in the overall system.
38  *
39  * @param start_index starting index for new states
40  */
41  void alloc(int start_index);
42 
43  /**
44  * Compute the left side portion of \f[$(C - J) \frac{dy}{dt} = f(y)$\f].
45  */
46  void lhs();
47 
48  /**
49  * Compute the right side portion of \f[$(C - J) \frac{dy}{dt} = f(y)$\f].
50  */
51  void rhs();
52 
53  /**
54  * Compute the residual: \f[$f(y) - C \frac{dy}{dt}$\f]
55  *
56  * @param y array of state variables
57  * @param yprime array of derivatives of state variables
58  * @param delta array to store the difference $f(y)-Cy'$
59  */
60  void dkres(double* y, double* yprime, double* delta);
61 
62  /**
63  * Initialize the dynamics.
64  *
65  * @remark Does this by calling f_init_. If f_init_ is NULL, initializes to
66  * values in y0_. If y0_ is NULL, initializes all states to 0.
67  */
68  void init();
69 
70  /**
71  * Update states to reflect the changes over a time-step.
72  *
73  * @remark When this function is called, the changes have already been
74  * computed by the solver. This just updates the local variables.
75  */
76  void update();
77 
78  /**
79  * Setup the map between voltages and states in y_.
80  *
81  * @param pv pointers to voltage nodes (set by this function)
82  * @param pvdot pointers to voltage derivatives (set by this
83  * function)
84  */
85  void dkmap(std::vector<double*>& pv, std::vector<double*>& pvdot);
86 
87  /**
88  * Destructor.
89  */
90  virtual ~NrnDAE();
91 
92  protected:
93  /**
94  * Constructor.
95  *
96  * @param cmat the matrix \f[$C$\f] in \f[$Cy'=f(y)$\f].
97  * @param yvec vector to store the state variables in
98  * @param y0 initial conditions
99  * @param nnode number of voltage equations to modify
100  * @param nodes pointers to voltage nodes
101  * @param elayer which potential layer to use for each voltage node
102  * @param f_init function to call during an finitialize
103  * @param data data to pass to f_init
104  *
105  * @remark If cmat is NULL, then assumes \f[$C$\f] is the identity matrix.
106  * @remark If f_init is non-NULL, that takes priority. Otherwise, if
107  * y0 is non-NULL, then initializes to those values. Otherwise
108  * initializes by setting all states to 0.
109  */
110  NrnDAE(Matrix* cmat,
111  Vect* const yvec,
112  Vect* const y0,
113  int nnode,
114  Node** const nodes,
115  Vect* const elayer,
116  void (*f_init)(void* data) = NULL,
117  void* const data = NULL);
118 
119  private:
120  /**
121  * The right-hand-side function.
122  *
123  * @param y the state variables
124  * @param yprime a vector to store the derivatives
125  * @param size the number of state variables
126  */
127  virtual void f_(Vect& y, Vect& yprime, int size) = 0;
128 
129  /**
130  * Compute the Jacobian.
131  *
132  * @param y the state variables
133  * @return Pointer to a MatrixMap containing the jacobian.
134  *
135  * @remark The calling function will not delete this pointer.
136  * @remark It is occasionally easier to return the Jacobian divided by
137  * a constant factor. If so, have jacobian_multiplier_ return a
138  * number that should be multiplied by the matrix returned by
139  * this function to get the true Jacobian.
140  */
141  virtual MatrixMap* jacobian_(Vect& y) = 0;
142 
143  /// Function used for initializing the state variables.
144  void (*f_init_)(void* data);
145 
146  /// Data to pass to f_init_.
147  void* data_;
148 
149  // value of jacobian_ must be multiplied by this value before use
150  virtual double jacobian_multiplier_() {
151  return 1;
152  }
153 
154  /**
155  * Additional allocation for subclasses.
156  *
157  * @remark Called during alloc(). Unless overriden, this function is empty.
158  */
159  virtual void alloc_(int size, int start, int nnode, Node** nodes, int* elayer);
160 
161  /// the matrix \f[$C$ in $C y' = f(y)$\f]
163 
164  /// identity matrix if constructed with \f[$C$\f] NULL; else NULL.
166 
167  /// vector of initial conditions
169 
170  /// vector to store the state variables in
172 
173  /// total number of states declared or modified in this object
174  int size_;
175 
176  /// mapping between the states in y and the states in the whole system
177  int* bmap_;
178 
179  /// Number of voltage nodes used by the dynamics.
180  int nnode_;
181 
182  /// Pointers to voltage nodes used by the dynamics.
184 
185  /// the position of the first added equation (if any) in the global system
186  int start_;
187 
188  /// temporary vector used for residual calculation.
190 
191  /// temporary vector used for residual calculation.
193 
194  /**
195  * Which voltage layers to read from.
196  *
197  * @remark Normally elements are 0 and refer to internal potential.
198  * Otherwise range from 1 to nlayer and refer to vext[elayer-1].
199  * vm+vext and vext must be placed in y for calculation of rhs
200  */
201  int* elayer_;
202 
203  /// Transfer any voltage states to y_.
204  void v2y();
205 };
206 
207 /**
208  * Add a NrnDAE object to the system.
209  *
210  * @param n The NrnDAE object (ie the dynamics) to add.
211  */
212 void nrndae_register(NrnDAE* n);
213 
214 /**
215  * Remove a NrnDAE object from the system.
216  *
217  * @param n The NrnDAE object (ie the dynamics) to remove.
218  */
219 void nrndae_deregister(NrnDAE* n);
220 
221 typedef std::list<NrnDAE*> NrnDAEPtrList;
222 typedef NrnDAEPtrList::const_iterator NrnDAEPtrListIterator;
NEURON Differential Algebraic Equations.
Definition: nrndae.h:27
int size_
total number of states declared or modified in this object
Definition: nrndae.h:174
void v2y()
Transfer any voltage states to y_.
Definition: nrndae.cpp:258
MatrixMap * c_
the matrix
Definition: nrndae.h:162
void rhs()
Compute the right side portion of.
Definition: nrndae.cpp:305
int start_
the position of the first added equation (if any) in the global system
Definition: nrndae.h:186
virtual ~NrnDAE()
Destructor.
Definition: nrndae.cpp:192
int nnode_
Number of voltage nodes used by the dynamics.
Definition: nrndae.h:180
virtual double jacobian_multiplier_()
Definition: nrndae.h:150
Vect cyp_
temporary vector used for residual calculation.
Definition: nrndae.h:189
virtual void f_(Vect &y, Vect &yprime, int size)=0
The right-hand-side function.
void alloc(int start_index)
Allocate space for these dynamics in the overall system.
Definition: nrndae.cpp:108
void lhs()
Compute the left side portion of.
Definition: nrndae.cpp:314
Vect yptmp_
temporary vector used for residual calculation.
Definition: nrndae.h:192
virtual void alloc_(int size, int start, int nnode, Node **nodes, int *elayer)
Additional allocation for subclasses.
Definition: nrndae.cpp:106
void update()
Update states to reflect the changes over a time-step.
Definition: nrndae.cpp:224
void * data_
Data to pass to f_init_.
Definition: nrndae.h:147
NrnDAE(Matrix *cmat, Vect *const yvec, Vect *const y0, int nnode, Node **const nodes, Vect *const elayer, void(*f_init)(void *data)=NULL, void *const data=NULL)
Constructor.
Definition: nrndae.cpp:141
void dkres(double *y, double *yprime, double *delta)
Compute the residual:
Definition: nrndae.cpp:277
int * bmap_
mapping between the states in y and the states in the whole system
Definition: nrndae.h:177
void dkmap(std::vector< double * > &pv, std::vector< double * > &pvdot)
Setup the map between voltages and states in y_.
Definition: nrndae.cpp:214
Matrix * assumed_identity_
identity matrix if constructed with
Definition: nrndae.h:165
Vect * y0_
vector of initial conditions
Definition: nrndae.h:168
Node ** nodes_
Pointers to voltage nodes used by the dynamics.
Definition: nrndae.h:183
void init()
Initialize the dynamics.
Definition: nrndae.cpp:236
virtual MatrixMap * jacobian_(Vect &y)=0
Compute the Jacobian.
Vect & y_
vector to store the state variables in
Definition: nrndae.h:171
int * elayer_
Which voltage layers to read from.
Definition: nrndae.h:201
void(* f_init_)(void *data)
Function used for initializing the state variables.
Definition: nrndae.h:144
int extra_eqn_count()
Find the number of state variables introduced by this object.
Definition: nrndae.cpp:207
#define data
Definition: md1redef.h:36
NrnDAEPtrList::const_iterator NrnDAEPtrListIterator
Definition: nrndae.h:222
std::list< NrnDAE * > NrnDAEPtrList
Definition: nrndae.h:221
void nrndae_register(NrnDAE *n)
Add a NrnDAE object to the system.
Definition: nrndae.cpp:18
void nrndae_deregister(NrnDAE *n)
Remove a NrnDAE object from the system.
Definition: nrndae.cpp:22
int const size_t const size_t n
Definition: nrngsl.h:10
#define NULL
Definition: spdefs.h:105
Definition: section.h:105