1: // 2: // Heccer : a compartmental solver that implements efficient Crank-Nicolson 3: // integration for neuronal models. 4: // 5: 6: ////////////////////////////////////////////////////////////////////////////// 7: //' 8: //' Heccer : testbed C implementation 9: //' 10: //' Copyright (C) 2006-2008 Hugo Cornelis 11: //' 12: //' functional ideas .. Hugo Cornelis, hugo.cornelis@gmail.com 13: //' 14: //' coding ............ Hugo Cornelis, hugo.cornelis@gmail.com 15: //' 16: ////////////////////////////////////////////////////////////////////////////// 17: 18: 19: #include <stdio.h> 20: #include <stdlib.h> 21: #include <string.h> 22: 23: #include "heccer/mathcomponent.h" 24: #include "heccer/mechanism.h" 25: 26: 27: static struct MathComponentInfo pmci[] = 28: { 29: MATH_TYPE_ChannelAct, ((char *)&((struct ChannelAct *)0)[1]) - ((char *)&((struct ChannelAct *)0)[0]), 30: MATH_TYPE_ChannelActConc, ((char *)&((struct ChannelActConc *)0)[1]) - ((char *)&((struct ChannelActConc *)0)[0]), 31: MATH_TYPE_ChannelActInact, ((char *)&((struct ChannelActInact *)0)[1]) - ((char *)&((struct ChannelActInact *)0)[0]), 32: MATH_TYPE_ChannelPersistentSteadyStateDualTau, ((char *)&((struct ChannelPersistentSteadyStateDualTau *)0)[1]) - ((char *)&((struct ChannelPersistentSteadyStateDualTau *)0)[0]), 33: MATH_TYPE_ChannelPersistentSteadyStateTau, ((char *)&((struct ChannelPersistentSteadyStateTau *)0)[1]) - ((char *)&((struct ChannelPersistentSteadyStateTau *)0)[0]), 34: MATH_TYPE_ChannelSpringMass, ((char *)&((struct ChannelSpringMass *)0)[1]) - ((char *)&((struct ChannelSpringMass *)0)[0]), 35: MATH_TYPE_ChannelSteadyStateSteppedTau, ((char *)&((struct ChannelSteadyStateSteppedTau *)0)[1]) - ((char *)&((struct ChannelSteadyStateSteppedTau *)0)[0]), 36: MATH_TYPE_ExponentialDecay, ((char *)&((struct ExponentialDecay *)0)[1]) - ((char *)&((struct ExponentialDecay *)0)[0]), 37: MATH_TYPE_InternalNernst, ((char *)&((struct InternalNernst *)0)[1]) - ((char *)&((struct InternalNernst *)0)[0]), 38: MATH_TYPE_SpikeGenerator, ((char *)&((struct SpikeGenerator *)0)[1]) - ((char *)&((struct SpikeGenerator *)0)[0]), 39: -1, -1, 40: }; 41: 42: 43: /// ************************************************************************** 44: /// 45: /// SHORT: MathComponentArrayCallocData() 46: /// 47: /// ARGS.: 48: /// 49: /// pmca...: math component array. 50: /// iTypes.: set of math component types to allocate for, -1 terminated. 51: /// 52: /// RTN..: int 53: /// 54: /// success of operation. 55: /// 56: /// DESCR: Allocate the math component data for the given set of types. 57: /// 58: /// As a side effect, sets the number of expected math components 59: /// to the number of types, and the cursor to zero. After this, 60: /// fill the array by calling for each math component 61: /// MathComponentArraySetAdvance(). 62: /// 63: /// ************************************************************************** 64: 65: int MathComponentArrayCallocData(struct MathComponentArray *pmca, int *piTypes) 66: { 67: //- set default result : not ok 68: 69: int iResult = 0; 70: 71: //- compute size 72: 73: int iSize = 0; 74: 75: int i; 76: 77: for (i = 0 ; piTypes[i] > 0 ; i++) 78: { 79: //- lookup the type int the size table 80: 81: struct MathComponentInfo *pmci = MathComponentInfoLookup(piTypes[i]); 82: 83: if (!pmci) 84: { 85: return(0); 86: } 87: 88: //- increment size to allocate 89: 90: int iChars = pmci->iChars; 91: 92: iSize += iChars; 93: } 94: 95: //- if we need to allocate something 96: 97: if (iSize) 98: { 99: //- allocate memory 100: 101: pmca->pmc = (struct MathComponent *)calloc(iSize, sizeof(char)); 102: 103: //- set cursor for filling the mathcomponent array 104: 105: pmca->iCursor = 0; 106: 107: pmca->pmcCursor = pmca->pmc; 108: 109: //- set the number of math components 110: 111: pmca->iMathComponents = i; 112: 113: //- clear out the index 114: 115: pmca->ppmcIndex = NULL; 116: } 117: 118: //- return result : ok 119: 120: return(1); 121: } 122: 123: 124: #ifdef HECCER_SOURCE_NEUROSPACES 125: 126: /// ************************************************************************** 127: /// 128: /// SHORT: MathComponentArrayLookupSerial() 129: /// 130: /// ARGS.: 131: /// 132: /// pmca....: math component array. 133: /// iSerial.: serial to search. 134: /// 135: /// RTN..: int 136: /// 137: /// index of matching math component, -1 for not found. 138: /// 139: /// DESCR: Look up a math component by serial. 140: /// 141: /// ************************************************************************** 142: 143: int 144: MathComponentArrayLookupSerial 145: (struct MathComponentArray *pmca, int iSerial) 146: { 147: //- set default result : not found 148: 149: int iResult = -1; 150: 151: //- loop over all mathcomponents 152: 153: struct MathComponent * pmc = pmca->pmc; 154: 155: int iMathComponent; 156: 157: for (iMathComponent = 0 ; iMathComponent < pmca->iMathComponents ; iMathComponent++) 158: { 159: //- if serials match 160: 161: if (pmc->iSerial == iSerial) 162: { 163: //- set result : current index 164: 165: iResult = iMathComponent; 166: 167: //- break searching loop 168: 169: break; 170: } 171: 172: //- advance to the next math component 173: 174: pmc = MathComponentNext(pmc); 175: } 176: 177: //- return result 178: 179: return(iResult); 180: } 181: 182: #endif 183: 184: 185: /// ************************************************************************** 186: /// 187: /// SHORT: MathComponentArraySetAdvance() 188: /// 189: /// ARGS.: 190: /// 191: /// pmca...: math component array. 192: /// pmc....: math component to add. 193: /// 194: /// RTN..: int 195: /// 196: /// success of operation. 197: /// 198: /// DESCR: Add math component at current cursor position, advance. 199: /// 200: /// NOTE.: 201: /// 202: /// There is no protection for overflows by checking the cursor 203: /// with the number of math components. 204: /// 205: /// ************************************************************************** 206: 207: int 208: MathComponentArraySetAdvance 209: (struct MathComponentArray *pmca, struct MathComponent *pmc) 210: { 211: //- set default result : failure 212: 213: int iResult = 0; 214: 215: //- determine size to copy 216: 217: int iType = pmc->iType; 218: 219: struct MathComponentInfo *pmci = MathComponentInfoLookup(iType); 220: 221: if (!pmci) 222: { 223: return(0); 224: } 225: 226: int iChars = pmci->iChars; 227: 228: //- copy the math component to the current cursor position 229: 230: memcpy(pmca->pmcCursor, pmc, iChars); 231: 232: //- advance the cursor 233: 234: pmca->iCursor++; 235: 236: pmca->pmcCursor = (struct MathComponent *)&((char *)pmca->pmcCursor)[iChars]; 237: 238: //- return result 239: 240: return(1); 241: } 242: 243: 244: /// ************************************************************************** 245: /// 246: /// SHORT: MathComponentCopyNext() 247: /// 248: /// ARGS.: 249: /// 250: /// pmcTarget.: math component target. 251: /// pmcSource.: math component source. 252: /// 253: /// RTN..: struct MathComponent * 254: /// 255: /// Next math component in the array, NULL for failure. 256: /// 257: /// DESCR: Copy a math component, advance to the next math component. 258: /// 259: /// The original content of pmcTarget is completely ignored and 260: /// overwritten. 261: /// 262: /// TODO: 263: /// 264: /// This need an additional helper function that takes an /// 265: /// non-linear array of math components and linearizes them in 266: /// memory. 267: /// 268: /// ************************************************************************** 269: 270: struct MathComponent * 271: MathComponentCopyNext 272: (struct MathComponent *pmcTarget, struct MathComponent *pmcSource) 273: { 274: //- set default result : failure 275: 276: struct MathComponent *pmcResult = NULL; 277: 278: //- determine size to copy 279: 280: int iType = pmcSource->iType; 281: 282: struct MathComponentInfo *pmci = MathComponentInfoLookup(iType); 283: 284: if (!pmci) 285: { 286: return(NULL); 287: } 288: 289: int iChars = pmci->iChars; 290: 291: //- copy the math component to the current cursor position 292: 293: memcpy(pmcTarget, pmcSource, iChars); 294: 295: //- set result 296: 297: pmcResult = MathComponentNext(pmcTarget); 298: 299: //- return result 300: 301: return(pmcResult); 302: } 303: 304: 305: /// ************************************************************************** 306: /// 307: /// SHORT: MathComponentInfoLookup() 308: /// 309: /// ARGS.: 310: /// 311: /// iType.: math component type. 312: /// 313: /// RTN..: struct MathComponentInfo * 314: /// 315: /// Math component info, respecting compilation options. 316: /// 317: /// DESCR: Lookup math component type, respecting compilation options. 318: /// 319: /// NOTE.: 320: /// 321: /// This function is for the purpose of constructing 322: /// intermediaries from C level. The info returned depends on 323: /// compilation options. See the test code for an example of its 324: /// use. 325: /// 326: /// ************************************************************************** 327: 328: struct MathComponentInfo * MathComponentInfoLookup(int iType) 329: { 330: //- set default result : failure 331: 332: struct MathComponentInfo *pmciResult = NULL; 333: 334: //- loop & search 335: 336: int j; 337: 338: for (j = 0 ; pmci[j].iType > 0 ; j++) 339: { 340: //- if found, set result 341: 342: if (pmci[j].iType == iType) 343: { 344: pmciResult = &pmci[j]; 345: 346: break; 347: } 348: } 349: 350: //- return result 351: 352: return pmciResult; 353: } 354: 355: 356: /// ************************************************************************** 357: /// 358: /// SHORT: MathComponentNext() 359: /// 360: /// ARGS.: 361: /// 362: /// pmc....: math component in the array. 363: /// 364: /// RTN..: struct MathComponent * 365: /// 366: /// Next math component, NULL for failure. 367: /// 368: /// DESCR: Access a math component, and lookup the next component. 369: /// 370: /// NOTE.: 371: /// 372: /// There is no protection for overflows by checking the cursor 373: /// with the number of math components. 374: /// 375: /// ************************************************************************** 376: 377: struct MathComponent * MathComponentNext(struct MathComponent *pmc) 378: { 379: //- set default result : next math component 380: 381: //- determine size 382: 383: int iType = pmc->iType; 384: 385: struct MathComponentInfo *pmci = MathComponentInfoLookup(iType); 386: 387: if (!pmci) 388: { 389: return(0); 390: } 391: 392: int iChars = pmci->iChars; 393: 394: struct MathComponent *pmcResult 395: = (struct MathComponent *)&((char *)pmc)[iChars]; 396: 397: //- return result 398: 399: return(pmcResult); 400: } 401: 402: 403: