section.h

Go to the documentation of this file.
00001 /* /local/src/master/nrn/src/nrnoc/section.h,v 1.4 1996/05/21 17:09:24 hines Exp */
00002 #ifndef section_h
00003 #define section_h
00004 
00005 /* In order to support oc objects containing sections, instead of vector
00006    of ordered sections, we now have a list (in the nmodl sense)
00007    of unordered sections. The lesser efficiency is ok because the
00008    number crunching is vectorized. ie only the user interface deals
00009    with sections and that needs to be convenient
00010 */
00011 /* Data structure for solving branching 1-D tree diffusion type equations.
00012    Vector of ordered sections each of which points to a vector of nodes.
00013    Each section must have at least one node. There may be 0 sections.
00014    The order of last node to first node is used in triangularization.
00015    First node to last is used in back substitution.
00016    The first node of a section is connected to some node of a section
00017      with lesser index.
00018 */
00019 /* An equation is associated with each node. d and rhs are the diagonal and
00020    right hand side respectively.  a is the effect of this node on the parent
00021    node's equation.  b is the effect of the parent node on this node's
00022    equation.
00023    d is assumed to be non-zero.
00024    d and rhs is calculated from the property list.
00025 */
00026 
00027 #if defined(__cplusplus)
00028 extern "C" {
00029 #endif
00030 
00031 #include "nrnredef.h"
00032 #include "options.h"
00033 #include "hoclist.h"
00034 
00035 /*#define DEBUGSOLVE 1*/
00036 #define xpop   hoc_xpop
00037 #define pc  hoc_pc
00038 #define spop   hoc_spop
00039 #define execerror hoc_execerror
00040 #include "hocdec.h"
00041 
00042 typedef struct Section {
00043    int refcount;     /* may be in more than one list */
00044    short    nnode;      /* Number of nodes for ith section */
00045    struct Section*   parentsec;  /* parent section of node 0 */
00046    struct Section* child;     /* root of the list of children
00047                   connected to this parent kept in
00048                   order of increasing x */
00049    struct Section*   sibling; /* used as list of sections that have same parent */
00050 
00051 
00052    /* the parentnode is only valid when tree_changed = 0 */
00053    struct Node*    parentnode;     /* parent node */  
00054    struct Node**  pnode;   /* Pointer to  pointer vector of node structures */
00055    int order;     /* index of this in secorder vector */
00056    short recalc_area_;  /* NODEAREA, NODERINV, diam, L need recalculation */
00057    short volatile_mark; /* for searching */
00058    void* volatile_ptr;  /* e.g. ShapeSection* */
00059 #if DIAMLIST
00060    short  npt3d;  /* number of 3-d points */
00061    short  pt3d_bsize; /* amount of allocated space for 3-d points */
00062    struct Pt3d *pt3d; /* list of 3d points with diameter */
00063    struct Pt3d *logical_connection; /* nil for legacy, otherwise specifies logical connection position (for translation) */
00064 #endif
00065    struct Prop *prop;   /* eg. length, etc. */
00066 } Section;
00067 
00068 #if DIAMLIST
00069 typedef struct Pt3d {
00070    float x,y,z,d; /* 3d point, microns */
00071    double arc;
00072 } Pt3d;
00073 #endif
00074 
00075 #if METHOD3
00076 typedef float NodeCoef;
00077 typedef double NodeVal;
00078 
00079 typedef struct Info3Coef {
00080    NodeVal current;  /* for use in next time step */
00081    NodeVal djdv0;
00082    NodeCoef coef0;      /* 5dx/12 */
00083    NodeCoef coefn;      /* 1dx/12 */
00084    NodeCoef coefjdot;   /* dx^2*ra/12 */
00085    NodeCoef coefdg;  /* dx/12 */
00086    NodeCoef coefj;      /* 1/(ra*dx) */
00087    struct Node* nd2; /* the node dx away in the opposite direction*/
00088 /* note above implies that nodes next to branches cannot have point processes
00089 and still be third order correct. Also nodes next to branches cannot themselves
00090 be branch points */
00091 } Info3Coef;
00092 
00093 typedef struct Info3Val {  /* storage to help build matrix efficiently */
00094    NodeVal GC;    /* doesn't include point processes */
00095    NodeVal EC;
00096    NodeCoef Cdt;
00097 } Info3Val;
00098 
00099 /*METHOD3*/
00100 #endif
00101 
00102 /* if any double is added after area then think about changing
00103 the notify_free_val parameter in node_free in solve.c
00104 */
00105 
00106 #define NODED(n) (*((n)->_d))
00107 #define NODERHS(n) (*((n)->_rhs))
00108 
00109 #undef NODEV /* sparc-sun-solaris2.9 */
00110 
00111 #if CACHEVEC == 0
00112 #define NODEA(n) ((n)->_a)
00113 #define NODEB(n) ((n)->_b)
00114 #define NODEV(n) ((n)->_v)
00115 #define NODEAREA(n) ((n)->_area)
00116 #else /* CACHEVEC */
00117 #define NODEV(n) (*((n)->_v))
00118 #define NODEAREA(n) ((n)->_area)
00119 #define NODERINV(n) ((n)->_rinv)
00120 #define VEC_A(i) (_nt->_actual_a[(i)])
00121 #define VEC_B(i) (_nt->_actual_b[(i)])
00122 #define VEC_D(i) (_nt->_actual_d[(i)])
00123 #define VEC_RHS(i) (_nt->_actual_rhs[(i)])
00124 #define VEC_V(i) (_nt->_actual_v[(i)])
00125 #define VEC_AREA(i) (_nt->_actual_area[(i)])
00126 #define NODEA(n) (VEC_A((n)->v_node_index))
00127 #define NODEB(n) (VEC_B((n)->v_node_index))
00128 #endif /* CACHEVEC */
00129 
00130 extern int use_sparse13;
00131 extern int use_cachevec;
00132 
00133 typedef struct Node {
00134 #if CACHEVEC == 0
00135    double   _v;         /* membrane potential */
00136    double _area;        /* area in um^2 but see treesetup.c */
00137    double   _a;         /* effect of node in parent equation */
00138    double   _b;         /* effect of parent in node equation */
00139 #else /* CACHEVEC */
00140    double   *_v;        /* membrane potential */
00141    double _area;        /* area in um^2 but see treesetup.c */
00142    double _rinv;        /* conductance uS from node to parent */
00143    double _v_temp;         /* vile necessity til actual_v allocated */
00144 #endif /* CACHEVEC */
00145    double*  _d;         /* diagonal element in node equation */
00146    double*  _rhs;       /* right hand side in node equation */
00147    double* _a_matelm;
00148    double* _b_matelm;
00149    int eqn_index_; /* sparse13 matrix row/col index */
00150          /* if no extnodes then = v_node_index +1*/
00151          /* each extnode adds nlayer more equations after this */
00152    struct Prop *prop;   /* Points to beginning of property list */
00153    Section* child;      /* section connected to this node */
00154                   /* 0 means no other section connected */
00155    Section* sec;     /* section this node is in */
00156 /* #if PARANEURON */
00157    struct Node* _classical_parent; /* needed for multisplit */
00158    struct NrnThread* _nt;
00159 /* #endif */
00160 #if EXTRACELLULAR
00161    struct Extnode* extnode;
00162 #endif
00163 
00164 #if EXTRAEQN
00165    struct Eqnblock *eqnblock; /* hook to other equations which
00166          need to be solved at the same time as the membrane
00167          potential. eg. fast changeing ionic concentrations */
00168 #endif /*MOREEQN*/
00169 
00170 #if DEBUGSOLVE
00171    double savd;
00172    double savrhs;
00173 #endif /*DEBUGSOLVE*/
00174 #if VECTORIZE
00175    int v_node_index; /* only used to calculate parent_node_indices*/
00176 #endif
00177    int sec_node_index_; /* to calculate segment index from *Node */
00178 #if METHOD3
00179    Info3Coef toparent;
00180    Info3Coef fromparent;
00181    Info3Val thisnode;
00182 #endif
00183 } Node;
00184 
00185 #if EXTRACELLULAR
00186 /* pruned to only work with sparse13 */
00187 #define  nlayer (EXTRACELLULAR)  /* first (0) layer is extracellular next to membrane */
00188 /*
00189 changing nlayer here means you have to change the explicit numbers
00190 nlayer-1 in the mechanism structure in extcell.c
00191 */
00192 typedef struct Extnode {
00193    double   *param;  /* points to extracellular parameter vector */
00194    /* v is membrane potential. so v internal = Node.v + Node.vext[0] */
00195    /* However, the Node equation is for v internal. */
00196    /* This is reconciled during update. */
00197    
00198    double   v[nlayer]; /* v external. */
00199    double   _a[nlayer];
00200    double   _b[nlayer];
00201    double* _d[nlayer];
00202    double* _rhs[nlayer]; /* d, rhs, a, and b are analogous to those in node */
00203    double* _a_matelm[nlayer];
00204    double* _b_matelm[nlayer];
00205    double* _x12[nlayer]; /* effect of v[layer] on eqn layer-1 (or internal)*/
00206    double* _x21[nlayer]; /* effect of v[layer-1 or internal] on eqn layer*/
00207 } Extnode;
00208 #endif
00209 
00210 #if !INCLUDEHOCH
00211 #include "hocdec.h"     /* Prop needs Datum and Datum needs Symbol */
00212 #endif
00213 
00214 #define PROP_PY_INDEX 10
00215 
00216 typedef struct Prop {
00217    struct Prop *next;   /* linked list of properties */
00218    short type;    /* type of membrane, e.g. passive, HH, etc. */
00219    short unused1; /* gcc and borland need pairs of shorts to align the same.*/
00220    int   param_size; /* for notifying hoc_free_val_array */
00221    double   *param;  /* vector of doubles for this property */
00222    Datum *dparam; /* usually vector of pointers to doubles
00223              of other properties but maybe other things as well
00224              for example one cable section property is a
00225              symbol */
00226    long _alloc_seq; /* for cache efficiency */
00227    Object* ob; /* nil if normal property, otherwise the object containing the data*/
00228 } Prop;
00229 
00230 extern double* nrn_prop_data_alloc(int type, int count, Prop* p);
00231 extern Datum* nrn_prop_datum_alloc(int type, int count, Prop* p);
00232 extern void nrn_prop_data_free(int type, double* pd);
00233 extern void nrn_prop_datum_free(int type, Datum* ppd);
00234 
00235 /* a point process is computed just like regular mechanisms. Ie it appears
00236 in the property list whose type specifies which allocation, current, and
00237 state functions to call.  This means some nodes have more properties than
00238 other nodes even in the same section.  The Point_process structure allows
00239 the interface to hoc variable names.
00240 Each variable symbol u.rng->type refers to the point process mechanism.
00241 The variable is treated as a vector
00242 variable whose first index specifies "which one" of that mechanisms insertion
00243 points we are talking about.  Finally the variable u.rng->index tells us
00244 where in the p-array to look.  The number of point_process vectors is the
00245 number of different point process types.  This is different from the
00246 mechanism type which enumerates all mechanisms including the point_processes.
00247 It is the responsibility of create_point_process to set up the vectors and
00248 fill in the symbol information.  However only after the process is given
00249 a location can the variables be set or accessed. This is because the
00250 allocation function may have to connect to some ionic parameters and the
00251 process exists primarily as a property of a node.
00252 */
00253 typedef struct Point_process {
00254    Section *sec;  /* section and node location for the point mechanism*/
00255    Node *node;
00256    Prop *prop; /* pointer to the actual property linked to the
00257             node property list */
00258    Object* ob; /* object that owns this process */
00259    void* presyn_; /* non-threshold presynapse for NetCon */
00260    void* nvi_; /* NrnVarIntegrator (for local step method) */
00261    void* _vnt; /* NrnThread* (for NET_RECEIVE and multicore) */
00262 } Point_process;
00263 
00264 #if EXTRAEQN
00265 /*Blocks of equations can hang off each node of the current conservation
00266 equations. These are equations which must be solved simultaneously
00267 because they depend on the voltage and affect the voltage. An example
00268 are fast changing ionic concentrations (or merely if we want to be
00269 able to calculate steady states using a stable method).
00270 */
00271 typedef struct Eqnblock {
00272    struct Eqnblock *eqnblock_next; /* may be several such blocks */
00273    Pfri  eqnblock_triang;  /* triangularization function */
00274    Pfri  eqnblock_bksub;   /* back substitution function */
00275    double   *eqnblock_data;
00276 #if 0
00277    the solving functions know how to find the following info from
00278    the eqnblock_data.
00279    double *eqnblock_row;   /* current conservation depends on states */
00280    double *eqnblock_col;   /* state equations depend on voltage */
00281    double *eqnblock_matrix; /* state equations depend on states */
00282    double *eqnblock_rhs:
00283    the functions merely take a pointer to the node and this Eqnblock
00284    in order to update the values of the diagonal, v, and the rhs
00285    The interface with EXTRACELLULAR makes things a bit more subtle.
00286    It seems clear that we will have to change the meaning of v to
00287    be membrane potential so that the internal potential is v + vext.
00288    This will avoid requiring two rows and two columns since
00289    the state equations will depend only on v and not vext.
00290    In fact, if vext did not have longitudinal relationships with
00291    other vext the extracellular mechanism could be implemented in
00292    this style.
00293 #endif
00294 } Eqnblock;
00295 #endif /*EXTRAEQN*/
00296 
00297 extern int nrn_global_ncell; /* note that for multiple threads all the rootnodes are no longer contiguous */
00298 extern hoc_List* section_list;   /* Where the Sections live */
00299 
00300 extern Section* chk_access();
00301 extern Section *sec_alloc();     /* Allocates a single section */
00302 #if defined(__cplusplus)
00303 extern void node_alloc(Section*, int);    /* Allocates node vectors in a section*/
00304 extern double section_length(Section*), nrn_diameter(Node*);
00305 extern double nrn_ghk(double, double, double, double);
00306 #else
00307 extern void node_alloc();     /* Allocates node vectors in a section*/
00308 extern double section_length(), nrn_diameter();
00309 extern double nrn_ghk();
00310 #endif
00311 extern Node* nrn_parent_node(Node*);
00312 
00313 /* loop over sections. Must previously declare Item* qsec. Contains the {! */
00314 #define ForAllSections(sec) \
00315    ITERATE(qsec, section_list) { Section* sec = hocSEC(qsec);
00316 
00317 #if METHOD3
00318 extern int _method3;
00319 #endif
00320 
00321 #include <multicore.h>
00322 
00323 extern int stoprun;
00324 #define tstopbit (1 << 15)
00325 #define tstopset stoprun |= tstopbit
00326 #define tstopunset stoprun &= (~tstopbit)
00327 /* cvode.event(tevent) sets this. Reset at beginning */
00328 /* of any hoc call for integration and before returning to hoc */
00329 
00330 
00331 #if defined(__cplusplus)
00332 }
00333 #endif
00334 
00335 #endif
00336 
00337 
Generated on Mon Jun 13 08:10:27 2011 for NEURON by  doxygen 1.6.3