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 <stdlib.h> 20: 21: #include "../../heccer/addressing.h" 22: #include "../../heccer/compartment.h" 23: #include "../../heccer/heccer.h" 24: #include "../../heccer/event.h" 25: #include "../../heccer/output.h" 26: 27: 28: #define HECCER_TEST_REPORTING_GRANULARITY 10000 29: #define HECCER_TEST_STEPS 10000 30: #define HECCER_TEST_TESTED_THINGS ( HECCER_DUMP_VM_COMPARTMENT_MATRIX \ 31: | HECCER_DUMP_VM_COMPARTMENT_DATA \ 32: | HECCER_DUMP_VM_COMPARTMENT_OPERATIONS \ 33: | HECCER_DUMP_VM_MECHANISM_DATA \ 34: | HECCER_DUMP_VM_MECHANISM_OPERATIONS \ 35: | HECCER_DUMP_VM_SUMMARY \ 36: ) 37: #define HECCER_TEST_TIME_STEP (1e-6) 38: 39: 40: struct Compartment compSource = 41: { 42: //m administrative overhead 43: 44: { 45: //m type of structure 46: 47: MATH_TYPE_Compartment, 48: 49: #ifdef HECCER_SOURCE_NEUROSPACES 50: 51: //m identification 52: 53: ADDRESSING_NEUROSPACES_2_HECCER(1000), 54: 55: #endif 56: 57: }, 58: 59: //m index of parent compartment, -1 for none 60: 61: -1, 62: 63: /* //m first mechanism */ 64: 65: /* NULL, */ 66: 67: /* //m number of mechanisms */ 68: 69: /* 0, */ 70: 71: //m descriptive values, alphabetical order 72: 73: /* double dCm; */ 74: 75: 4.57537e-11, // unscaled 0.0164, 76: 77: /* double dEm; */ 78: 79: -0.08, 80: 81: /* double dInitVm; */ 82: 83: -0.065, 84: 85: /* double dInject; */ 86: 87: 2e-9, 88: 89: /* double dRa; */ 90: 91: 360502, // unscaled 2.5, 92: 93: /* double dRm; */ 94: 95: 3.58441e+08, // unscaled 1 96: }; 97: 98: 99: //v a regular delayed rectifier, taken from the genesis website 100: 101: struct ChannelAct caKdrSource = 102: { 103: //m administrative overhead 104: 105: { 106: //m type of structure 107: 108: MATH_TYPE_ChannelAct, 109: 110: #ifdef HECCER_SOURCE_NEUROSPACES 111: 112: //m identification 113: 114: ADDRESSING_NEUROSPACES_2_HECCER(2000), 115: 116: #endif 117: 118: }, 119: 120: //m first set of descriptive values, alphabetical order 121: 122: //m initial reversal potential 123: 124: -0.085, 125: 126: //m get reversal potential from this intermediary, -1 for none 127: 128: -1, 129: 130: //m maximal conductance when all channels are permissive 131: 132: 1.004349542e-06, 133: 134: //m contributes to this concentration pool, -1 for none, boolean indicator only. 135: 136: -1, 137: 138: //m activation description 139: 140: { 141: //m power, for a standard heccer, something between 1 and 4 or so. 142: 143: 4, 144: 145: //m gate definition 146: 147: { 148: //m initial value, commonly forward over backward steady states 149: 150: 0.3176769506, 151: 152: //m corresponding index in tables, set to -1 for initialization. 153: 154: -1, 155: 156: { 157: //m forward kinetiks, commonly denoted with alpha or non-perm to perm rate 158: 159: { 160: //m multiplier 161: 162: -550.0, 163: 164: //m multiplier membrane dependence, 0.0 for no dependence 165: 166: 10000, 167: 168: //m 2b: multiplier membrane dependence offset, 0.0 for no dependence 169: 170: 0.0, 171: 172: //m choose between nominator or denominator, 1 means nominator, -1 173: //m means denominator 174: 175: -1.0, 176: 177: //m nominator or denominator offset 178: 179: -1.0, 180: 181: //m membrane offset 182: 183: 0.055, 184: 185: //m denormalized time constant 186: 187: -0.01, 188: }, 189: 190: //m backward kinetiks, commonly denoted with beta or perm to non-perm rate 191: 192: { 193: //m multiplier 194: 195: 125.0, 196: 197: //m multiplier membrane dependence, 0.0 for no dependence 198: 199: 0.0, 200: 201: //m 2b: multiplier membrane dependence offset, 0.0 for no dependence 202: 203: 0.0, 204: 205: //m choose between nominator or denominator, 1 means nominator, -1 206: //m means denominator 207: 208: -1.0, 209: 210: //m nominator or denominator offset 211: 212: 0.0, 213: 214: //m membrane offset 215: 216: 0.065, 217: 218: //m denormalized time constant 219: 220: 0.08, 221: }, 222: }, 223: }, 224: }, 225: 226: }; 227: 228: 229: //v a simple fast sodium channel 230: 231: struct ChannelActInact caiNaFSource = 232: { 233: //m administrative overhead 234: 235: { 236: //m type of structure 237: 238: MATH_TYPE_ChannelActInact, 239: 240: #ifdef HECCER_SOURCE_NEUROSPACES 241: 242: //m identification 243: 244: ADDRESSING_NEUROSPACES_2_HECCER(3000), 245: 246: #endif 247: 248: }, 249: 250: //m first set of descriptive values, alphabetical order 251: 252: //m initial reversal potential 253: 254: 0.045, 255: 256: //m get reversal potential from this intermediary, -1 for none 257: 258: -1, 259: 260: //m maximal conductance when all channels are permissive 261: 262: 0.00001, 263: 264: //m contributes to this concentration pool, -1 for none, boolean indicator only. 265: 266: -1, 267: 268: //m activation description 269: 270: { 271: //m power, for a standard heccer, something between 1 and 4 or so. 272: 273: 3, 274: 275: //m gate definition 276: 277: { 278: //m initial value, commonly forward over backward steady states 279: 280: 0.01224204035, 281: 282: //m corresponding index in tables, set to -1 for initialization. 283: 284: -1, 285: 286: { 287: //m forward kinetiks, commonly denoted with alpha or non-perm to perm rate 288: 289: { 290: //m multiplier 291: 292: 35.0e3, 293: 294: //m multiplier membrane dependence, 0.0 for no dependence 295: 296: 0.0, 297: 298: //m 2b: multiplier membrane dependence offset, 0.0 for no dependence 299: 300: 0.0, 301: 302: //m choose between nominator or denominator, 1 means nominator, -1 303: //m means denominator 304: 305: -1.0, 306: 307: //m nominator or denominator offset 308: 309: 0.0, 310: 311: //m membrane offset 312: 313: 5.0e-3, 314: 315: //m denormalized time constant 316: 317: -10.0e-3, 318: }, 319: 320: //m backward kinetiks, commonly denoted with beta or perm to non-perm rate 321: 322: { 323: //m multiplier 324: 325: 7.0e3, 326: 327: //m multiplier membrane dependence, 0.0 for no dependence 328: 329: 0.0, 330: 331: //m 2b: multiplier membrane dependence offset, 0.0 for no dependence 332: 333: 0.0, 334: 335: //m choose between nominator or denominator, 1 means nominator, -1 336: //m means denominator 337: 338: -1.0, 339: 340: //m nominator or denominator offset 341: 342: 0.0, 343: 344: //m membrane offset 345: 346: 65.0e-3, 347: 348: //m denormalized time constant 349: 350: 20.0e-3, 351: }, 352: }, 353: }, 354: }, 355: 356: //m inactivation description 357: 358: { 359: //m power, for a standard heccer, something between 1 and 4 or so. 360: 361: 1, 362: 363: //m gate definition 364: 365: { 366: //m initial value, commonly forward over backward steady states 367: 368: 0.1930685015, 369: 370: //m corresponding index in tables, set to -1 for initialization. 371: 372: -1, 373: 374: { 375: //m forward kinetiks, commonly denoted with alpha or non-perm to perm rate 376: 377: { 378: //m multiplier 379: 380: 0.225e3, 381: 382: //m multiplier membrane dependence, 0.0 for no dependence 383: 384: 0.0, 385: 386: //m 2b: multiplier membrane dependence offset, 0.0 for no dependence 387: 388: 0.0, 389: 390: //m choose between nominator or denominator, 1 means nominator, -1 391: //m means denominator 392: 393: -1.0, 394: 395: //m nominator or denominator offset 396: 397: 1.0, 398: 399: //m membrane offset 400: 401: 80.0e-3, 402: 403: //m denormalized time constant 404: 405: 10.0e-3, 406: }, 407: 408: //m backward kinetiks, commonly denoted with beta or perm to non-perm rate 409: 410: { 411: //m multiplier 412: 413: 7.5e3, 414: 415: //m multiplier membrane dependence, 0.0 for no dependence 416: 417: 0.0, 418: 419: //m 2b: multiplier membrane dependence offset, 0.0 for no dependence 420: 421: 0.0, 422: 423: //m choose between nominator or denominator, 1 means nominator, -1 424: //m means denominator 425: 426: -1.0, 427: 428: //m nominator or denominator offset 429: 430: 0.0, 431: 432: //m membrane offset 433: 434: -3.0e-3, 435: 436: //m denormalized time constant 437: 438: -18.0e-3, 439: }, 440: }, 441: }, 442: }, 443: }; 444: 445: 446: struct SpikeGenerator sgSource = 447: { 448: //m administrative overhead 449: 450: { 451: //m type of structure 452: 453: MATH_TYPE_SpikeGenerator, 454: 455: #ifdef HECCER_SOURCE_NEUROSPACES 456: 457: //m identification 458: 459: ADDRESSING_NEUROSPACES_2_HECCER(4000), 460: 461: #endif 462: 463: }, 464: 465: //m refractory time 466: 467: 0.001, 468: 469: //m spiking threshold 470: 471: 0.0, 472: 473: //m reset value, FLT_MAX for none 474: 475: FLT_MAX, 476: 477: //m table in event distributor with targets 478: 479: 0, 480: }; 481: 482: 483: int piC2m[] = 484: { 485: 3, 486: -1, 487: }; 488: 489: 490: struct MathComponentArray mcaSource = 491: { 492: //m number of math components 493: 494: 3, 495: 496: //m math component data 497: 498: NULL, 499: 500: //m math component index, initialize to NULL 501: 502: NULL, 503: 504: }; 505: 506: 507: struct Intermediary interSource = 508: { 509: //m compartment array 510: 511: 1, 512: 513: &compSource, 514: 515: //m all other mathematical components 516: 517: &mcaSource, 518: 519: //m compartment 2 first mechanism number 520: 521: piC2m, 522: }; 523: 524: 525: struct Compartment compTarget1 = 526: { 527: //m administrative overhead 528: 529: { 530: //m type of structure 531: 532: MATH_TYPE_Compartment, 533: 534: #ifdef HECCER_SOURCE_NEUROSPACES 535: 536: //m identification 537: 538: ADDRESSING_NEUROSPACES_2_HECCER(5000), 539: 540: #endif 541: 542: }, 543: 544: //m index of parent compartment, -1 for none 545: 546: -1, 547: 548: /* //m first mechanism */ 549: 550: /* NULL, */ 551: 552: /* //m number of mechanisms */ 553: 554: /* 0, */ 555: 556: //m descriptive values, alphabetical order 557: 558: /* double dCm; */ 559: 560: 4.57537e-11, // unscaled 0.0164, 561: 562: /* double dEm; */ 563: 564: -0.08, 565: 566: /* double dInitVm; */ 567: 568: -0.065, 569: 570: /* double dInject; */ 571: 572: 0.0, 573: 574: /* double dRa; */ 575: 576: 360502, // unscaled 2.5, 577: 578: /* double dRm; */ 579: 580: 3.58441e+08, // unscaled 1 581: }; 582: 583: 584: //s spring mass channel (synaptic channel) 585: 586: struct ChannelSpringMass csmTarget1 = 587: { 588: //m administrative overhead 589: 590: { 591: //m type of structure 592: 593: MATH_TYPE_ChannelSpringMass, 594: 595: #ifdef HECCER_SOURCE_NEUROSPACES 596: 597: //m identification 598: 599: ADDRESSING_NEUROSPACES_2_HECCER(6000), 600: 601: #endif 602: 603: }, 604: 605: //m initial reversal potential 606: 607: 0.0, 608: 609: //m get reversal potential from this intermediary, -1 for none 610: 611: -1, 612: 613: //m maximal conductance 614: 615: 6.87071723162637e-10, 616: 617: //m contributes to this concentration pool, -1 for none, boolean indicator only. 618: 619: -1, 620: 621: //m random activation frequency 622: 623: 0.0, 624: 625: //m first exponential initial value 626: 627: 0.0, 628: 629: //m second exponential initial value 630: 631: 0.0, 632: 633: //m corresponding index in tables, set to -1 for initialization. 634: 635: -1, 636: 637: //m event time table (FLT_MAX terminated) 638: 639: NULL, 640: 641: //m yaml file with event time table, the previous must be NULL. 642: 643: //! during compilation, the file is converted to a double array 644: //! and fills the previous entry. 645: 646: NULL, 647: 648: //m parameters 649: 650: { 651: //m first time constant 652: 653: 5e-4, 654: 655: //m second time constant 656: 657: 1.2e-3, 658: }, 659: 660: }; 661: 662: 663: int piC2mTarget1[] = 664: { 665: 1, 666: -1, 667: }; 668: 669: 670: struct MathComponentArray mcaTarget1 = 671: { 672: //m number of math components 673: 674: 1, 675: 676: //m math component data 677: 678: &csmTarget1.mc, 679: 680: //m math component index, initialize to NULL 681: 682: NULL, 683: 684: }; 685: 686: 687: struct Intermediary interTarget1 = 688: { 689: //m compartment array 690: 691: 1, 692: 693: &compTarget1, 694: 695: //m all other mathematical components 696: 697: &mcaTarget1, 698: 699: //m compartment 2 first mechanism number 700: 701: piC2mTarget1, 702: }; 703: 704: 705: struct Compartment compTarget2 = 706: { 707: //m administrative overhead 708: 709: { 710: //m type of structure 711: 712: MATH_TYPE_Compartment, 713: 714: #ifdef HECCER_SOURCE_NEUROSPACES 715: 716: //m identification 717: 718: ADDRESSING_NEUROSPACES_2_HECCER(7000), 719: 720: #endif 721: 722: }, 723: 724: //m index of parent compartment, -1 for none 725: 726: -1, 727: 728: /* //m first mechanism */ 729: 730: /* NULL, */ 731: 732: /* //m number of mechanisms */ 733: 734: /* 0, */ 735: 736: //m descriptive values, alphabetical order 737: 738: /* double dCm; */ 739: 740: 4.57537e-11, // unscaled 0.0164, 741: 742: /* double dEm; */ 743: 744: -0.08, 745: 746: /* double dInitVm; */ 747: 748: -0.065, 749: 750: /* double dInject; */ 751: 752: 0.0, 753: 754: /* double dRa; */ 755: 756: 360502, // unscaled 2.5, 757: 758: /* double dRm; */ 759: 760: 3.58441e+08, // unscaled 1 761: }; 762: 763: 764: //s spring mass channel (synaptic channel) 765: 766: struct ChannelSpringMass csmTarget2 = 767: { 768: //m administrative overhead 769: 770: { 771: //m type of structure 772: 773: MATH_TYPE_ChannelSpringMass, 774: 775: #ifdef HECCER_SOURCE_NEUROSPACES 776: 777: //m identification 778: 779: ADDRESSING_NEUROSPACES_2_HECCER(8000), 780: 781: #endif 782: 783: }, 784: 785: //m initial reversal potential 786: 787: 0.0, 788: 789: //m get reversal potential from this intermediary, -1 for none 790: 791: -1, 792: 793: //m maximal conductance 794: 795: 6.87071723162637e-10, 796: 797: //m contributes to this concentration pool, -1 for none, boolean indicator only. 798: 799: -1, 800: 801: //m random activation frequency 802: 803: 0.0, 804: 805: //m first exponential initial value 806: 807: 0.0, 808: 809: //m second exponential initial value 810: 811: 0.0, 812: 813: //m corresponding index in tables, set to -1 for initialization. 814: 815: -1, 816: 817: //m event time table (FLT_MAX terminated) 818: 819: NULL, 820: 821: //m yaml file with event time table, the previous must be NULL. 822: 823: //! during compilation, the file is converted to a double array 824: //! and fills the previous entry. 825: 826: NULL, 827: 828: //m parameters 829: 830: { 831: //m first time constant 832: 833: 5e-4, 834: 835: //m second time constant 836: 837: 1.2e-3, 838: }, 839: 840: }; 841: 842: 843: int piC2mTarget2[] = 844: { 845: 1, 846: -1, 847: }; 848: 849: 850: struct MathComponentArray mcaTarget2 = 851: { 852: //m number of math components 853: 854: 1, 855: 856: //m math component data 857: 858: &csmTarget2.mc, 859: 860: //m math component index, initialize to NULL 861: 862: NULL, 863: 864: }; 865: 866: 867: struct Intermediary interTarget2 = 868: { 869: //m compartment array 870: 871: 1, 872: 873: &compTarget2, 874: 875: //m all other mathematical components 876: 877: &mcaTarget2, 878: 879: //m compartment 2 first mechanism number 880: 881: piC2mTarget2, 882: }; 883: 884: 885: #include "../../heccer/eventdistributor.h" 886: 887: struct EventDistributorMatrix pedm[] = 888: { 889: //! for HeccerOutput object 890: 891: { 892: //m target object, a solver, a HeccerOutput, or so 893: 894: NULL, 895: 896: //m target subcomponent identification 897: 898: -1, 899: 900: //m called function 901: 902: NULL, 903: 904: //m serial in the model container 905: 906: -1, 907: }, 908: 909: //! for event queuer 910: 911: { 912: //m target object, a solver, a HeccerOutput, or so 913: 914: NULL, 915: 916: //m target subcomponent identification 917: 918: -1, 919: 920: //m called function 921: 922: NULL, 923: 924: //m serial in the model container 925: 926: -1, 927: }, 928: 929: //! terminator 930: 931: { 932: //m target object, a solver, a HeccerOutput, or so 933: 934: NULL, 935: 936: //m target subcomponent identification 937: 938: -1, 939: 940: //m called function 941: 942: NULL, 943: 944: //m serial in the model container 945: 946: -1, 947: }, 948: 949: }; 950: 951: struct EventDistributorData edd = 952: { 953: //m number of connections in the matrix 954: 955: 3, 956: 957: //m last used 958: 959: 2, 960: 961: //m array of targets 962: 963: pedm, 964: }; 965: 966: 967: struct EventDistributor ed = 968: { 969: //m service specific data 970: 971: &edd, 972: 973: //m distribute an event over the targets 974: 975: EventDistributorSend, 976: }; 977: 978: 979: struct EventQueuerMatrix peqm[] = 980: { 981: //! for target heccer 1 982: 983: { 984: //m target object, a solver or so 985: 986: NULL, 987: 988: //m target object, an index into a array of double ? 989: 990: 4, 991: 992: //m connection delay 993: 994: 0.001, 995: 996: //m connection weight 997: 998: 1.0, 999: 1000: //m called function 1001: 1002: HeccerEventSet, 1003: }, 1004: 1005: //! for target heccer 2 1006: 1007: { 1008: //m target object, a solver or so 1009: 1010: NULL, 1011: 1012: //m target object, an index into a array of double ? 1013: 1014: 4, 1015: 1016: //m connection delay 1017: 1018: 0.002, 1019: 1020: //m connection weight 1021: 1022: 2.0, 1023: 1024: //m called function 1025: 1026: HeccerEventSet, 1027: }, 1028: 1029: //! terminator 1030: 1031: { 1032: //m target object, a solver or so 1033: 1034: NULL, 1035: 1036: //m target object, an index into a array of double ? 1037: 1038: 0, 1039: 1040: //m connection delay 1041: 1042: FLT_MAX, 1043: 1044: //m connection weight 1045: 1046: FLT_MAX, 1047: 1048: //m called function 1049: 1050: NULL, 1051: }, 1052: 1053: //! terminator 1054: 1055: { 1056: //m target object, a solver or so 1057: 1058: NULL, 1059: 1060: //m target object, an index into a array of double ? 1061: 1062: 0, 1063: 1064: //m connection delay 1065: 1066: 0.0, 1067: 1068: //m connection weight 1069: 1070: 0.0, 1071: 1072: //m called function 1073: 1074: NULL, 1075: }, 1076: }; 1077: 1078: struct EventQueuerData eqd = 1079: { 1080: //m array translating name service serials to event queuer target index 1081: 1082: 2, 1083: 1084: { 1085: { 6000, 0, }, 1086: { 8000, 1, }, 1087: }, 1088: 1089: //m array of targets 1090: 1091: peqm, 1092: }; 1093: 1094: 1095: struct EventQueuer eq = 1096: { 1097: //m service specific data 1098: 1099: &eqd, 1100: 1101: /* //m hand an event over to the event queuer */ 1102: 1103: /* //! decouples the event queuer from the source */ 1104: 1105: /* EventQueuerEnqueue, */ 1106: 1107: //m forward an event from queuer to receiver 1108: 1109: //! decouples the event queuer from the receiver 1110: 1111: EventQueuerDequeue, 1112: 1113: }; 1114: 1115: 1116: struct OutputGenerator *pogSpikeSource = NULL; 1117: struct OutputGenerator * pogVmSource = NULL; 1118: 1119: /* double *pdVm = NULL; */ 1120: 1121: char pcStep[100] = ""; 1122: 1123: /* #include "main.h" */ 1124: 1125: 1126: /* #define main(argc,argv) not_used(argc,argv) */ 1127: 1128: 1129: /* #include "main.c" */ 1130: 1131: 1132: //v accessible from the outside if needed 1133: 1134: struct Heccer *pheccerSource = NULL; 1135: struct Heccer *pheccerTarget1 = NULL; 1136: struct Heccer *pheccerTarget2 = NULL; 1137: 1138: 1139: int main(int argc, char *argv[]) 1140: { 1141: //- set default result : ok 1142: 1143: int iResult = EXIT_SUCCESS; 1144: 1145: //- determine intermediary size, and allocate 1146: 1147: struct MathComponentInfo *pmciKdrSource = MathComponentInfoLookup(caKdrSource.mc.iType); 1148: 1149: struct MathComponentInfo *pmciNaFSource = MathComponentInfoLookup(caiNaFSource.mc.iType); 1150: 1151: struct MathComponentInfo *pmciSpikerSource = MathComponentInfoLookup(sgSource.mc.iType); 1152: 1153: int iCharsSource = pmciKdrSource->iChars + pmciNaFSource->iChars + pmciSpikerSource->iChars; 1154: 1155: void *pmcSource = calloc(sizeof(char), iCharsSource); 1156: 1157: //- prepare the mechanism intermediary 1158: 1159: struct ChannelAct *pcaSource = (struct ChannelAct *)pmcSource; 1160: 1161: *pcaSource = caKdrSource; 1162: 1163: struct ChannelActInact *pcaiSource = (struct ChannelActInact *)&((char *)pcaSource)[pmciKdrSource->iChars]; 1164: 1165: *pcaiSource = caiNaFSource; 1166: 1167: struct SpikeGenerator *psgSource = (struct SpikeGenerator *)&((char *)pcaiSource)[pmciNaFSource->iChars]; 1168: 1169: *psgSource = sgSource; 1170: 1171: //- link the intermediary 1172: 1173: mcaSource.pmc = pmcSource; 1174: 1175: //- create an output generator 1176: 1177: pogSpikeSource = OutputGeneratorNew("/tmp/output_spike_source"); 1178: 1179: //- link spiking element to output generator 1180: 1181: pedm[0].pvObject = pogSpikeSource; 1182: pedm[0].pvFunction = OutputGeneratorTimedStep; 1183: 1184: //- link spiking element to the event queuer 1185: 1186: //! see also below, same developer comment 1187: 1188: pedm[1].pvObject = &peqm[0]; 1189: pedm[1].pvObject = &eq; 1190: pedm[1].iTarget = 0; 1191: pedm[1].pvFunction = EventQueuerEnqueue; 1192: 1193: //- create output elements 1194: 1195: pogVmSource = OutputGeneratorNew("/tmp/output_vm_source"); 1196: 1197: //d prepare output of membrane potential and spikes 1198: 1199: #define HECCER_TEST_INITIATE \ 1200: double *pdVmSource = HeccerAddressCompartmentVariable(pheccerSource, 0, "Vm"); \ 1201: OutputGeneratorAddVariable(pogVmSource, "Vm", pdVmSource); \ 1202: double *pdSpikeSource = HeccerAddressMechanismVariable(pheccerSource, 2, "spike"); \ 1203: OutputGeneratorAddVariable(pogSpikeSource, "spike", pdSpikeSource) 1204: 1205: //d generate output of membrane potential each step 1206: 1207: #define HECCER_TEST_OUTPUT \ 1208: OutputGeneratorAnnotatedStep(pogVmSource, sprintf(pcStep, "%i", i) ? pcStep : "sprintf() failed") 1209: 1210: //- allocate the heccer, for the event distributor service 1211: 1212: //! the source is constructed overhere and further initialized in simulate(), 1213: //! the targets are constructed in simulate() only. Needs to be cleaned up. 1214: 1215: pheccerSource = HeccerNew("source", NULL, &ed, NULL); 1216: 1217: pheccerTarget1 = HeccerNew("target1", NULL, NULL, &eq); 1218: 1219: pheccerTarget2 = HeccerNew("target2", NULL, NULL, &eq); 1220: 1221: //- do the simulation 1222: 1223: int simulate(int argc, char *argv[]); 1224: 1225: simulate(argc,argv); 1226: 1227: //- finish the simulation output 1228: 1229: OutputGeneratorFinish(pogVmSource); 1230: 1231: OutputGeneratorFinish(pogSpikeSource); 1232: 1233: //- add the simulation output to the program output 1234: 1235: WriteOutput("/tmp/output_vm_source"); 1236: 1237: WriteOutput("/tmp/output_spike_source"); 1238: 1239: //- return result 1240: 1241: return(iResult); 1242: } 1243: 1244: 1245: //o To use this file : 1246: //o 1247: //o set the variable 'inter' to an intermediary representation, 1248: //o #define HECCER_TEST_STEPS 1 1249: //o #define HECCER_TEST_TESTED_THINGS to a dump selection, 1250: //o and so on for the defines below, when not set they get a 1251: //o sensible default value. 1252: //o #include this file, compile, run and parse the output. 1253: //o 1254: //o Heccer construction can also be done using the 1255: //o HECCER_TEST_CONSTRUCT macro, in which case the global variable 1256: //o pheccer must be preallocated. 1257: //o 1258: //o Tests with multiple heccers must not use this file. 1259: //o 1260: 1261: #ifndef HECCER_TEST_CONSTRUCT_SOURCE 1262: #define HECCER_TEST_CONSTRUCT_SOURCE \ 1263: memcpy(&pheccerSource->inter, &interSource, sizeof(interSource)); \ 1264: pheccerSource->iStatus = HECCER_STATUS_PHASE_2 1265: #endif 1266: 1267: #ifndef HECCER_TEST_CONSTRUCT_TARGET1 1268: #define HECCER_TEST_CONSTRUCT_TARGET1 \ 1269: memcpy(&pheccerTarget1->inter, &interTarget1, sizeof(interTarget1)); \ 1270: pheccerTarget1->iStatus = HECCER_STATUS_PHASE_2 1271: #endif 1272: 1273: #ifndef HECCER_TEST_CONSTRUCT_TARGET2 1274: #define HECCER_TEST_CONSTRUCT_TARGET2 \ 1275: memcpy(&pheccerTarget2->inter, &interTarget2, sizeof(interTarget2)); \ 1276: pheccerTarget2->iStatus = HECCER_STATUS_PHASE_2 1277: #endif 1278: 1279: #ifndef HECCER_TEST_INITIATE 1280: #define HECCER_TEST_INITIATE ((void)1) 1281: #endif 1282: 1283: #ifndef HECCER_TEST_INTERVAL_DEFAULT_START 1284: #define HECCER_TEST_INTERVAL_DEFAULT_START (-0.1) 1285: #endif 1286: 1287: #ifndef HECCER_TEST_INTERVAL_DEFAULT_END 1288: #define HECCER_TEST_INTERVAL_DEFAULT_END (0.05) 1289: #endif 1290: 1291: #ifndef HECCER_TEST_INTERVAL_DEFAULT_ENTRIES 1292: #define HECCER_TEST_INTERVAL_DEFAULT_ENTRIES 3000 1293: #endif 1294: 1295: #ifndef HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES 1296: #define HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES 149 1297: #endif 1298: 1299: #ifndef HECCER_TEST_OUTPUT 1300: #define HECCER_TEST_OUTPUT ((void)1) 1301: #endif 1302: 1303: #ifndef HECCER_TEST_REPORTING_GRANULARITY 1304: #define HECCER_TEST_REPORTING_GRANULARITY 1 1305: #endif 1306: 1307: #ifndef HECCER_TEST_STEPS 1308: #define HECCER_TEST_STEPS 10 1309: #endif 1310: 1311: #ifndef HECCER_TEST_TESTED_THINGS 1312: #define HECCER_TEST_TESTED_THINGS HECCER_DUMP_ALL 1313: #endif 1314: 1315: #ifndef HECCER_TEST_TIME_GRANULARITY 1316: #define HECCER_TEST_TIME_GRANULARITY (1e-9) 1317: #endif 1318: 1319: #ifndef HECCER_TEST_TIME_STEP 1320: #define HECCER_TEST_TIME_STEP (2e-5) 1321: #endif 1322: 1323: 1324: int WriteOutput(char *pcFilename); 1325: 1326: int WriteOutput(char *pcFilename) 1327: { 1328: //- set default result : ok 1329: 1330: int iResult = 1; 1331: 1332: //- copy the file content to stdout 1333: 1334: FILE *pfile = fopen(pcFilename, "r"); 1335: 1336: char pc[10000]; 1337: 1338: size_t st = fread(pc, sizeof(char), sizeof(pc), pfile); 1339: 1340: while (st == 10000) 1341: { 1342: fwrite(pc, sizeof(char), st, stdout); 1343: 1344: st = fread(pc, sizeof(char), sizeof(pc), pfile); 1345: } 1346: 1347: fwrite(pc, sizeof(char), st, stdout); 1348: 1349: //- return result 1350: 1351: return(iResult); 1352: } 1353: 1354: 1355: int simulate(int argc, char *argv[]); 1356: 1357: int simulate(int argc, char *argv[]) 1358: { 1359: //t use argv for heccer options 1360: 1361: //- set default result : ok 1362: 1363: int iResult = EXIT_SUCCESS; 1364: 1365: //- instantiate a heccer with an initialized intermediary 1366: 1367: //! note: test definition is allowed to allocate the heccer, with services. 1368: 1369: if (!pheccerSource) 1370: { 1371: pheccerSource = HeccerNewP2("source", &interSource); 1372: } 1373: else 1374: { 1375: HECCER_TEST_CONSTRUCT_SOURCE; 1376: } 1377: 1378: //- instantiate a heccer with an initialized intermediary 1379: 1380: //! note: test definition is allowed to allocate the heccer, with services. 1381: 1382: if (!pheccerTarget1) 1383: { 1384: pheccerTarget1 = HeccerNewP2("target1", &interTarget1); 1385: } 1386: else 1387: { 1388: HECCER_TEST_CONSTRUCT_TARGET1; 1389: } 1390: 1391: //- instantiate a heccer with an initialized intermediary 1392: 1393: //! note: test definition is allowed to allocate the heccer, with services. 1394: 1395: if (!pheccerTarget2) 1396: { 1397: pheccerTarget2 = HeccerNewP2("target2", &interTarget2); 1398: } 1399: else 1400: { 1401: HECCER_TEST_CONSTRUCT_TARGET2; 1402: } 1403: 1404: //t need sensible API to set options I guess. 1405: 1406: pheccerSource->dStep = HECCER_TEST_TIME_STEP; 1407: 1408: pheccerSource->ho.dIntervalStart = HECCER_TEST_INTERVAL_DEFAULT_START; 1409: 1410: pheccerSource->ho.dIntervalEnd = HECCER_TEST_INTERVAL_DEFAULT_END; 1411: 1412: //t should set test defaults for basal activator tables. 1413: 1414: /* pheccerSource->ho.dBasalActivatorStart = HECCER_TEST_INTERVAL_DEFAULT_START; */ 1415: 1416: /* pheccerSource->ho.dBasalActivatorEnd = HECCER_TEST_INTERVAL_DEFAULT_END; */ 1417: 1418: pheccerSource->ho.iIntervalEntries = HECCER_TEST_INTERVAL_DEFAULT_ENTRIES; 1419: 1420: pheccerSource->ho.iSmallTableSize = HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES; 1421: 1422: //- build indices for optimization 1423: 1424: HeccerCompileP2(pheccerSource); 1425: 1426: //- compile to byte code 1427: 1428: HeccerCompileP3(pheccerSource); 1429: 1430: //- initiate values 1431: 1432: HeccerInitiate(pheccerSource); 1433: 1434: //t need sensible API to set options I guess. 1435: 1436: pheccerTarget1->dStep = HECCER_TEST_TIME_STEP; 1437: 1438: pheccerTarget1->ho.dIntervalStart = HECCER_TEST_INTERVAL_DEFAULT_START; 1439: 1440: pheccerTarget1->ho.dIntervalEnd = HECCER_TEST_INTERVAL_DEFAULT_END; 1441: 1442: //t should set test defaults for basal activator tables. 1443: 1444: /* pheccerTarget1->ho.dBasalActivatorStart = HECCER_TEST_INTERVAL_DEFAULT_START; */ 1445: 1446: /* pheccerTarget1->ho.dBasalActivatorEnd = HECCER_TEST_INTERVAL_DEFAULT_END; */ 1447: 1448: pheccerTarget1->ho.iIntervalEntries = HECCER_TEST_INTERVAL_DEFAULT_ENTRIES; 1449: 1450: pheccerTarget1->ho.iSmallTableSize = HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES; 1451: 1452: //- build indices for optimization 1453: 1454: HeccerCompileP2(pheccerTarget1); 1455: 1456: //- compile to byte code 1457: 1458: HeccerCompileP3(pheccerTarget1); 1459: 1460: //- initiate values 1461: 1462: HeccerInitiate(pheccerTarget1); 1463: 1464: //t need sensible API to set options I guess. 1465: 1466: pheccerTarget2->dStep = HECCER_TEST_TIME_STEP; 1467: 1468: pheccerTarget2->ho.dIntervalStart = HECCER_TEST_INTERVAL_DEFAULT_START; 1469: 1470: pheccerTarget2->ho.dIntervalEnd = HECCER_TEST_INTERVAL_DEFAULT_END; 1471: 1472: //t should set test defaults for basal activator tables. 1473: 1474: /* pheccerTarget2->ho.dBasalActivatorStart = HECCER_TEST_INTERVAL_DEFAULT_START; */ 1475: 1476: /* pheccerTarget2->ho.dBasalActivatorEnd = HECCER_TEST_INTERVAL_DEFAULT_END; */ 1477: 1478: pheccerTarget2->ho.iIntervalEntries = HECCER_TEST_INTERVAL_DEFAULT_ENTRIES; 1479: 1480: pheccerTarget2->ho.iSmallTableSize = HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES; 1481: 1482: //- build indices for optimization 1483: 1484: HeccerCompileP2(pheccerTarget2); 1485: 1486: //- compile to byte code 1487: 1488: HeccerCompileP3(pheccerTarget2); 1489: 1490: //- initiate values 1491: 1492: HeccerInitiate(pheccerTarget2); 1493: 1494: //- link event queuer to springmass of target 1 1495: 1496: //! see also above, same developer comment 1497: 1498: peqm[0].pvObject = pheccerTarget1; 1499: 1500: //- link event queuer to springmass of target 2 1501: 1502: //! see also above, same developer comment 1503: 1504: peqm[1].pvObject = pheccerTarget2; 1505: 1506: //- initialize test specific things 1507: 1508: HECCER_TEST_INITIATE; 1509: 1510: //- initial dump 1511: 1512: //! funny : the first '---' in the output are taken as an option 1513: //! by Expect.pm, which complicates testing a bit. So just 1514: //! removed. 1515: 1516: /* fprintf(stdout, "-------\n"); */ 1517: 1518: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "Initiated\n"); 1519: 1520: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerSource, stdout, HECCER_TEST_TESTED_THINGS); 1521: 1522: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget1, stdout, HECCER_TEST_TESTED_THINGS); 1523: 1524: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget2, stdout, HECCER_TEST_TESTED_THINGS); 1525: 1526: //v final report needed ? 1527: 1528: int iFinalReport = 0; 1529: 1530: //- a couple of times 1531: 1532: int i; 1533: 1534: for (i = 0; i < HECCER_TEST_STEPS ; i++) 1535: { 1536: //- update the current simulation time. 1537: 1538: double dSimulationTime = i * HECCER_TEST_TIME_STEP + HECCER_TEST_TIME_GRANULARITY; 1539: 1540: //- step 1541: 1542: HeccerHeccs(pheccerSource, dSimulationTime); 1543: 1544: HeccerHeccs(pheccerTarget1, dSimulationTime); 1545: 1546: HeccerHeccs(pheccerTarget2, dSimulationTime); 1547: 1548: EventQueuerProcess(&eq); 1549: 1550: //- generate user specified output 1551: 1552: HECCER_TEST_OUTPUT; 1553: 1554: //- dump 1555: 1556: if (i % HECCER_TEST_REPORTING_GRANULARITY == 0) 1557: { 1558: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "-------\n"); 1559: 1560: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "Iteration %i\n", i); 1561: 1562: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerSource, stdout, HECCER_TEST_TESTED_THINGS); 1563: 1564: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget1, stdout, HECCER_TEST_TESTED_THINGS); 1565: 1566: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget2, stdout, HECCER_TEST_TESTED_THINGS); 1567: } 1568: else 1569: { 1570: iFinalReport = 1; 1571: } 1572: } 1573: 1574: //- add a final report if necessary 1575: 1576: if (iFinalReport) 1577: { 1578: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "-------\n"); 1579: 1580: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "Final Iteration\n", i); 1581: 1582: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerSource, stdout, HECCER_TEST_TESTED_THINGS); 1583: 1584: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget1, stdout, HECCER_TEST_TESTED_THINGS); 1585: 1586: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget2, stdout, HECCER_TEST_TESTED_THINGS); 1587: } 1588: 1589: //- return result 1590: 1591: return(iResult); 1592: } 1593: 1594: 1595: