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