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/event.h" 24: #include "../../heccer/heccer.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 OutputGenerator *pogSpikeSource = NULL; 888: struct OutputGenerator * pogVmSource = NULL; 889: 890: /* double *pdVm = NULL; */ 891: 892: char pcStep[100] = ""; 893: 894: /* #include "main.h" */ 895: 896: 897: /* #define main(argc,argv) not_used(argc,argv) */ 898: 899: 900: /* #include "main.c" */ 901: 902: 903: //v accessible from the outside if needed 904: 905: struct Heccer *pheccerSource = NULL; 906: struct Heccer *pheccerTarget1 = NULL; 907: struct Heccer *pheccerTarget2 = NULL; 908: 909: 910: int main(int argc, char *argv[]) 911: { 912: //- set default result : ok 913: 914: int iResult = EXIT_SUCCESS; 915: 916: //- determine intermediary size, and allocate 917: 918: struct MathComponentInfo *pmciKdrSource = MathComponentInfoLookup(caKdrSource.mc.iType); 919: 920: struct MathComponentInfo *pmciNaFSource = MathComponentInfoLookup(caiNaFSource.mc.iType); 921: 922: struct MathComponentInfo *pmciSpikerSource = MathComponentInfoLookup(sgSource.mc.iType); 923: 924: int iCharsSource = pmciKdrSource->iChars + pmciNaFSource->iChars + pmciSpikerSource->iChars; 925: 926: void *pmcSource = calloc(sizeof(char), iCharsSource); 927: 928: //- prepare the mechanism intermediary 929: 930: struct ChannelAct *pcaSource = (struct ChannelAct *)pmcSource; 931: 932: *pcaSource = caKdrSource; 933: 934: struct ChannelActInact *pcaiSource = (struct ChannelActInact *)&((char *)pcaSource)[pmciKdrSource->iChars]; 935: 936: *pcaiSource = caiNaFSource; 937: 938: struct SpikeGenerator *psgSource = (struct SpikeGenerator *)&((char *)pcaiSource)[pmciNaFSource->iChars]; 939: 940: *psgSource = sgSource; 941: 942: //- link the intermediary 943: 944: mcaSource.pmc = pmcSource; 945: 946: //- create an output generator 947: 948: pogSpikeSource = OutputGeneratorNew("/tmp/output_spike_source"); 949: 950: //- create output elements 951: 952: pogVmSource = OutputGeneratorNew("/tmp/output_vm_source"); 953: 954: //d prepare output of membrane potential and spikes 955: 956: #define HECCER_TEST_INITIATE \ 957: double *pdVmSource = HeccerAddressCompartmentVariable(pheccerSource, 0, "Vm"); \ 958: OutputGeneratorAddVariable(pogVmSource, "Vm", pdVmSource); \ 959: double *pdSpikeSource = HeccerAddressMechanismVariable(pheccerSource, 2, "spike"); \ 960: OutputGeneratorAddVariable(pogSpikeSource, "spike", pdSpikeSource) 961: 962: //d generate output of membrane potential each step 963: 964: #define HECCER_TEST_OUTPUT \ 965: OutputGeneratorAnnotatedStep(pogVmSource, sprintf(pcStep, "%i", i) ? pcStep : "sprintf() failed") 966: 967: //- do the simulation 968: 969: int simulate(int argc, char *argv[]); 970: 971: simulate(argc,argv); 972: 973: //- finish the simulation output 974: 975: OutputGeneratorFinish(pogVmSource); 976: 977: OutputGeneratorFinish(pogSpikeSource); 978: 979: //- add the simulation output to the program output 980: 981: WriteOutput("/tmp/output_vm_source"); 982: 983: WriteOutput("/tmp/output_spike_source"); 984: 985: //- return result 986: 987: return(iResult); 988: } 989: 990: 991: //o To use this file : 992: //o 993: //o set the variable 'inter' to an intermediary representation, 994: //o #define HECCER_TEST_STEPS 1 995: //o #define HECCER_TEST_TESTED_THINGS to a dump selection, 996: //o and so on for the defines below, when not set they get a 997: //o sensible default value. 998: //o #include this file, compile, run and parse the output. 999: //o 1000: //o Heccer construction can also be done using the 1001: //o HECCER_TEST_CONSTRUCT macro, in which case the global variable 1002: //o pheccer must be preallocated. 1003: //o 1004: //o Tests with multiple heccers must not use this file. 1005: //o 1006: 1007: #ifndef HECCER_TEST_CONSTRUCT_SOURCE 1008: #define HECCER_TEST_CONSTRUCT_SOURCE \ 1009: memcpy(&pheccerSource->inter, &interSource, sizeof(interSource)); \ 1010: pheccerSource->iStatus = HECCER_STATUS_PHASE_2 1011: #endif 1012: 1013: #ifndef HECCER_TEST_CONSTRUCT_TARGET1 1014: #define HECCER_TEST_CONSTRUCT_TARGET1 \ 1015: memcpy(&pheccerTarget1->inter, &interTarget1, sizeof(interTarget1)); \ 1016: pheccerTarget1->iStatus = HECCER_STATUS_PHASE_2 1017: #endif 1018: 1019: #ifndef HECCER_TEST_CONSTRUCT_TARGET2 1020: #define HECCER_TEST_CONSTRUCT_TARGET2 \ 1021: memcpy(&pheccerTarget2->inter, &interTarget2, sizeof(interTarget2)); \ 1022: pheccerTarget2->iStatus = HECCER_STATUS_PHASE_2 1023: #endif 1024: 1025: #ifndef HECCER_TEST_INITIATE 1026: #define HECCER_TEST_INITIATE ((void)1) 1027: #endif 1028: 1029: #ifndef HECCER_TEST_INTERVAL_DEFAULT_START 1030: #define HECCER_TEST_INTERVAL_DEFAULT_START (-0.1) 1031: #endif 1032: 1033: #ifndef HECCER_TEST_INTERVAL_DEFAULT_END 1034: #define HECCER_TEST_INTERVAL_DEFAULT_END (0.05) 1035: #endif 1036: 1037: #ifndef HECCER_TEST_INTERVAL_DEFAULT_ENTRIES 1038: #define HECCER_TEST_INTERVAL_DEFAULT_ENTRIES 3000 1039: #endif 1040: 1041: #ifndef HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES 1042: #define HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES 149 1043: #endif 1044: 1045: #ifndef HECCER_TEST_OUTPUT 1046: #define HECCER_TEST_OUTPUT ((void)1) 1047: #endif 1048: 1049: #ifndef HECCER_TEST_REPORTING_GRANULARITY 1050: #define HECCER_TEST_REPORTING_GRANULARITY 1 1051: #endif 1052: 1053: #ifndef HECCER_TEST_STEPS 1054: #define HECCER_TEST_STEPS 10 1055: #endif 1056: 1057: #ifndef HECCER_TEST_TESTED_THINGS 1058: #define HECCER_TEST_TESTED_THINGS HECCER_DUMP_ALL 1059: #endif 1060: 1061: #ifndef HECCER_TEST_TIME_GRANULARITY 1062: #define HECCER_TEST_TIME_GRANULARITY (1e-9) 1063: #endif 1064: 1065: #ifndef HECCER_TEST_TIME_STEP 1066: #define HECCER_TEST_TIME_STEP (2e-5) 1067: #endif 1068: 1069: 1070: int WriteOutput(char *pcFilename); 1071: 1072: int WriteOutput(char *pcFilename) 1073: { 1074: //- set default result : ok 1075: 1076: int iResult = 1; 1077: 1078: //- copy the file content to stdout 1079: 1080: FILE *pfile = fopen(pcFilename, "r"); 1081: 1082: char pc[10000]; 1083: 1084: size_t st = fread(pc, sizeof(char), sizeof(pc), pfile); 1085: 1086: while (st == 10000) 1087: { 1088: fwrite(pc, sizeof(char), st, stdout); 1089: 1090: st = fread(pc, sizeof(char), sizeof(pc), pfile); 1091: } 1092: 1093: fwrite(pc, sizeof(char), st, stdout); 1094: 1095: //- return result 1096: 1097: return(iResult); 1098: } 1099: 1100: 1101: int simulate(int argc, char *argv[]); 1102: 1103: int simulate(int argc, char *argv[]) 1104: { 1105: //t use argv for heccer options 1106: 1107: //- set default result : ok 1108: 1109: int iResult = EXIT_SUCCESS; 1110: 1111: //- construct a connection matrix for the event distributor 1112: 1113: struct EventQueuerMatrix peqm[] = 1114: { 1115: //! for target heccer 1 1116: 1117: { 1118: //m target object, a solver or so 1119: 1120: NULL, 1121: 1122: //m target object, an index into a array of double ? 1123: 1124: 4, 1125: 1126: //m connection delay 1127: 1128: 0.001, 1129: 1130: //m connection weight 1131: 1132: 1.0, 1133: 1134: //m called function 1135: 1136: HeccerEventSet, 1137: }, 1138: 1139: //! for target heccer 2 1140: 1141: { 1142: //m target object, a solver or so 1143: 1144: NULL, 1145: 1146: //m target object, an index into a array of double ? 1147: 1148: 4, 1149: 1150: //m connection delay 1151: 1152: 0.002, 1153: 1154: //m connection weight 1155: 1156: 2.0, 1157: 1158: //m called function 1159: 1160: HeccerEventSet, 1161: }, 1162: 1163: //! terminator 1164: 1165: { 1166: //m target object, a solver or so 1167: 1168: NULL, 1169: 1170: //m target object, an index into a array of double ? 1171: 1172: 0, 1173: 1174: //m connection delay 1175: 1176: FLT_MAX, 1177: 1178: //m connection weight 1179: 1180: FLT_MAX, 1181: 1182: //m called function 1183: 1184: NULL, 1185: }, 1186: 1187: }; 1188: 1189: //- allocate event queuer 1190: 1191: struct EventQueuer *peq = EventQueuerNew(peqm); 1192: 1193: //- initialize the serial to connection matrix index convertor 1194: 1195: if (!EventQueuerSerial2ConnectionIndexAdd(peq, 6000, 0)) 1196: { 1197: exit(1); 1198: } 1199: 1200: if (!EventQueuerSerial2ConnectionIndexAdd(peq, 8000, 1)) 1201: { 1202: exit(2); 1203: } 1204: 1205: if (!EventQueuerSerial2ConnectionIndexSort(peq)) 1206: { 1207: exit(3); 1208: } 1209: 1210: //- construct a connection matrix for the event distributor 1211: 1212: struct EventDistributorMatrix pedm[] = 1213: { 1214: //! for HeccerOutput object 1215: 1216: { 1217: //m target object, a solver, a HeccerOutput, or so 1218: 1219: pogSpikeSource, 1220: 1221: //m target subcomponent identification 1222: 1223: -1, 1224: 1225: //m called function 1226: 1227: OutputGeneratorTimedStep, 1228: 1229: //m serial in the model container 1230: 1231: -1, 1232: }, 1233: 1234: //! for event queuer 1235: 1236: { 1237: //m target object, a solver, a HeccerOutput, or so 1238: 1239: peq, // &peqm[0], 1240: 1241: //m target subcomponent identification 1242: 1243: 0, 1244: 1245: //m called function 1246: 1247: EventQueuerEnqueue, 1248: 1249: //m serial in the model container 1250: 1251: -1, 1252: }, 1253: 1254: //! terminator 1255: 1256: { 1257: //m target object, a solver, a HeccerOutput, or so 1258: 1259: NULL, 1260: 1261: //m target subcomponent identification 1262: 1263: -1, 1264: 1265: //m called function 1266: 1267: NULL, 1268: 1269: //m serial in the model container 1270: 1271: -1, 1272: }, 1273: 1274: }; 1275: 1276: struct EventDistributorData edd = 1277: { 1278: //m number of connections in the matrix 1279: 1280: 3, 1281: 1282: //m last used 1283: 1284: 2, 1285: 1286: //m array of targets 1287: 1288: pedm, 1289: }; 1290: 1291: 1292: //- allocate event distributor 1293: 1294: struct EventDistributor *ped = EventDistributorNew(&edd); 1295: 1296: //- allocate the heccer, for the event distributor service 1297: 1298: //! the source is constructed overhere and further initialized in simulate(), 1299: //! the targets are constructed in simulate() only. Needs to be cleaned up. 1300: 1301: pheccerSource = HeccerNew("source", NULL, ped, NULL); 1302: 1303: pheccerTarget1 = HeccerNew("target1", NULL, NULL, peq); 1304: 1305: pheccerTarget2 = HeccerNew("target2", NULL, NULL, peq); 1306: 1307: //- instantiate a heccer with an initialized intermediary 1308: 1309: //! note: test definition is allowed to allocate the heccer, with services. 1310: 1311: if (!pheccerSource) 1312: { 1313: pheccerSource = HeccerNewP2("source", &interSource); 1314: } 1315: else 1316: { 1317: HECCER_TEST_CONSTRUCT_SOURCE; 1318: } 1319: 1320: //- instantiate a heccer with an initialized intermediary 1321: 1322: //! note: test definition is allowed to allocate the heccer, with services. 1323: 1324: if (!pheccerTarget1) 1325: { 1326: pheccerTarget1 = HeccerNewP2("target1", &interTarget1); 1327: } 1328: else 1329: { 1330: HECCER_TEST_CONSTRUCT_TARGET1; 1331: } 1332: 1333: //- instantiate a heccer with an initialized intermediary 1334: 1335: //! note: test definition is allowed to allocate the heccer, with services. 1336: 1337: if (!pheccerTarget2) 1338: { 1339: pheccerTarget2 = HeccerNewP2("target2", &interTarget2); 1340: } 1341: else 1342: { 1343: HECCER_TEST_CONSTRUCT_TARGET2; 1344: } 1345: 1346: //t need sensible API to set options I guess. 1347: 1348: pheccerSource->dStep = HECCER_TEST_TIME_STEP; 1349: 1350: pheccerSource->ho.dIntervalStart = HECCER_TEST_INTERVAL_DEFAULT_START; 1351: 1352: pheccerSource->ho.dIntervalEnd = HECCER_TEST_INTERVAL_DEFAULT_END; 1353: 1354: //t should set test defaults for basal activator tables. 1355: 1356: /* pheccerSource->ho.dBasalActivatorStart = HECCER_TEST_INTERVAL_DEFAULT_START; */ 1357: 1358: /* pheccerSource->ho.dBasalActivatorEnd = HECCER_TEST_INTERVAL_DEFAULT_END; */ 1359: 1360: pheccerSource->ho.iIntervalEntries = HECCER_TEST_INTERVAL_DEFAULT_ENTRIES; 1361: 1362: pheccerSource->ho.iSmallTableSize = HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES; 1363: 1364: //- build indices for optimization 1365: 1366: HeccerCompileP2(pheccerSource); 1367: 1368: //- compile to byte code 1369: 1370: HeccerCompileP3(pheccerSource); 1371: 1372: //- initiate values 1373: 1374: HeccerInitiate(pheccerSource); 1375: 1376: //t need sensible API to set options I guess. 1377: 1378: pheccerTarget1->dStep = HECCER_TEST_TIME_STEP; 1379: 1380: pheccerTarget1->ho.dIntervalStart = HECCER_TEST_INTERVAL_DEFAULT_START; 1381: 1382: pheccerTarget1->ho.dIntervalEnd = HECCER_TEST_INTERVAL_DEFAULT_END; 1383: 1384: //t should set test defaults for basal activator tables. 1385: 1386: /* pheccerTarget1->ho.dBasalActivatorStart = HECCER_TEST_INTERVAL_DEFAULT_START; */ 1387: 1388: /* pheccerTarget1->ho.dBasalActivatorEnd = HECCER_TEST_INTERVAL_DEFAULT_END; */ 1389: 1390: pheccerTarget1->ho.iIntervalEntries = HECCER_TEST_INTERVAL_DEFAULT_ENTRIES; 1391: 1392: pheccerTarget1->ho.iSmallTableSize = HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES; 1393: 1394: //- build indices for optimization 1395: 1396: HeccerCompileP2(pheccerTarget1); 1397: 1398: //- compile to byte code 1399: 1400: HeccerCompileP3(pheccerTarget1); 1401: 1402: //- initiate values 1403: 1404: HeccerInitiate(pheccerTarget1); 1405: 1406: //t need sensible API to set options I guess. 1407: 1408: pheccerTarget2->dStep = HECCER_TEST_TIME_STEP; 1409: 1410: pheccerTarget2->ho.dIntervalStart = HECCER_TEST_INTERVAL_DEFAULT_START; 1411: 1412: pheccerTarget2->ho.dIntervalEnd = HECCER_TEST_INTERVAL_DEFAULT_END; 1413: 1414: //t should set test defaults for basal activator tables. 1415: 1416: /* pheccerTarget2->ho.dBasalActivatorStart = HECCER_TEST_INTERVAL_DEFAULT_START; */ 1417: 1418: /* pheccerTarget2->ho.dBasalActivatorEnd = HECCER_TEST_INTERVAL_DEFAULT_END; */ 1419: 1420: pheccerTarget2->ho.iIntervalEntries = HECCER_TEST_INTERVAL_DEFAULT_ENTRIES; 1421: 1422: pheccerTarget2->ho.iSmallTableSize = HECCER_TEST_INTERPOL_INTERVAL_DEFAULT_ENTRIES; 1423: 1424: //- build indices for optimization 1425: 1426: HeccerCompileP2(pheccerTarget2); 1427: 1428: //- compile to byte code 1429: 1430: HeccerCompileP3(pheccerTarget2); 1431: 1432: //- initiate values 1433: 1434: HeccerInitiate(pheccerTarget2); 1435: 1436: //- link event queuer to springmass of target 1 1437: 1438: //! see also above, same developer comment 1439: 1440: peqm[0].pvObject = pheccerTarget1; 1441: 1442: //- link event queuer to springmass of target 2 1443: 1444: //! see also above, same developer comment 1445: 1446: peqm[1].pvObject = pheccerTarget2; 1447: 1448: //- initialize test specific things 1449: 1450: HECCER_TEST_INITIATE; 1451: 1452: //- initial dump 1453: 1454: //! funny : the first '---' in the output are taken as an option 1455: //! by Expect.pm, which complicates testing a bit. So just 1456: //! removed. 1457: 1458: /* fprintf(stdout, "-------\n"); */ 1459: 1460: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "Initiated\n"); 1461: 1462: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerSource, stdout, HECCER_TEST_TESTED_THINGS); 1463: 1464: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget1, stdout, HECCER_TEST_TESTED_THINGS); 1465: 1466: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget2, stdout, HECCER_TEST_TESTED_THINGS); 1467: 1468: //v final report needed ? 1469: 1470: int iFinalReport = 0; 1471: 1472: //- a couple of times 1473: 1474: int i; 1475: 1476: for (i = 0; i < HECCER_TEST_STEPS ; i++) 1477: { 1478: //- update the current simulation time. 1479: 1480: double dSimulationTime = i * HECCER_TEST_TIME_STEP + HECCER_TEST_TIME_GRANULARITY; 1481: 1482: //- step 1483: 1484: HeccerHeccs(pheccerSource, dSimulationTime); 1485: 1486: HeccerHeccs(pheccerTarget1, dSimulationTime); 1487: 1488: HeccerHeccs(pheccerTarget2, dSimulationTime); 1489: 1490: EventQueuerProcess(peq); 1491: 1492: //- generate user specified output 1493: 1494: HECCER_TEST_OUTPUT; 1495: 1496: //- dump 1497: 1498: if (i % HECCER_TEST_REPORTING_GRANULARITY == 0) 1499: { 1500: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "-------\n"); 1501: 1502: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "Iteration %i\n", i); 1503: 1504: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerSource, stdout, HECCER_TEST_TESTED_THINGS); 1505: 1506: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget1, stdout, HECCER_TEST_TESTED_THINGS); 1507: 1508: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget2, stdout, HECCER_TEST_TESTED_THINGS); 1509: } 1510: else 1511: { 1512: iFinalReport = 1; 1513: } 1514: } 1515: 1516: //- add a final report if necessary 1517: 1518: if (iFinalReport) 1519: { 1520: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "-------\n"); 1521: 1522: HECCER_TEST_TESTED_THINGS && fprintf(stdout, "Final Iteration\n", i); 1523: 1524: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerSource, stdout, HECCER_TEST_TESTED_THINGS); 1525: 1526: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget1, stdout, HECCER_TEST_TESTED_THINGS); 1527: 1528: HECCER_TEST_TESTED_THINGS && HeccerDump(pheccerTarget2, stdout, HECCER_TEST_TESTED_THINGS); 1529: } 1530: 1531: //- return result 1532: 1533: return(iResult); 1534: } 1535: 1536: 1537: