file:/local_home/local_home/hugo/neurospaces_project/heccer/source/c/snapshots/0/vclamp.c (Mon Jun 16 00:04:16 2008
) HOME
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 <math.h>
20: #include <stdio.h>
21: #include <stdlib.h>
22: #include <string.h>
23:
24:
25: #include "heccer/vclamp.h"
26:
27:
28: /// **************************************************************************
29: ///
30: /// SHORT: VClampAddVariable()
31: ///
32: /// ARGS.:
33: ///
34: /// pvc.........: voltage clamper.
35: /// pvVoltage...: pointer to the voltage variable, assumed is double *
36: /// pvInjector..: pointer to the variable for injected current.
37: ///
38: /// RTN..: int
39: ///
40: /// success of operation.
41: ///
42: /// DESCR: Clamp the given voltage variable, using the given injector.
43: ///
44: /// **************************************************************************
45:
46: int
47: VClampAddVariable
48: (struct VClamp * pvc, void *pvVoltage, void *pvInjector)
49: {
50: //- set default result: ok
51:
52: int iResult = 1;
53:
54: if (pvc->iClampsActive >= 1)
55: {
56: return(0);
57: }
58:
59: //- set next variable
60:
61: pvc->pdVoltage = (double *)pvVoltage;
62:
63: pvc->pdInjector = (double *)pvInjector;
64:
65: pvc->iClampsActive++;
66:
67: //- return result
68:
69: return(iResult);
70: }
71:
72:
73: /// **************************************************************************
74: ///
75: /// SHORT: VClampFinish()
76: ///
77: /// ARGS.:
78: ///
79: /// pvc...: voltage clamper.
80: ///
81: /// RTN..: int
82: ///
83: /// success of operation.
84: ///
85: /// DESCR: Free the voltage clamper.
86: ///
87: /// **************************************************************************
88:
89: int VClampFinish(struct VClamp * pvc)
90: {
91: //- set default result: ok
92:
93: int iResult = 1;
94:
95: //- free all allocated memory
96:
97: free(pvc);
98:
99: //- return result
100:
101: return(iResult);
102: }
103:
104:
105: /// **************************************************************************
106: ///
107: /// SHORT: VClampInitiate()
108: ///
109: /// ARGS.:
110: ///
111: /// pvc...: voltage clamper.
112: ///
113: /// RTN..: int
114: ///
115: /// success of operation.
116: ///
117: /// DESCR: Initiate the voltage clamper.
118: ///
119: /// **************************************************************************
120:
121: int VClampInitiate(struct VClamp * pvc)
122: {
123: //- set default result: ok
124:
125: int iResult = 1;
126:
127: //- just clear out some varialbes...
128:
129: //t should initialize from a stream as heccer does.
130:
131: pvc->dEIntegral = 0;
132: pvc->dEPrevious = 0;
133: pvc->dOutput = 0;
134:
135: //- return result
136:
137: return(iResult);
138: }
139:
140:
141: /// **************************************************************************
142: ///
143: /// SHORT: VClampNew()
144: ///
145: /// ARGS.:
146: ///
147: /// pcName..: name of this object.
148: ///
149: /// RTN..: struct VClamp *
150: ///
151: /// voltage clamper, NULL for failure.
152: ///
153: /// DESCR: voltage clamper.
154: ///
155: /// **************************************************************************
156:
157: struct VClamp * VClampNew(char *pcName)
158: {
159: //- set default result: failure
160:
161: struct VClamp * pvcResult = NULL;
162:
163: //- allocate voltage clamper
164:
165: pvcResult = (struct VClamp *)calloc(1, sizeof(struct VClamp));
166:
167: if (!pvcResult)
168: {
169: return(NULL);
170: }
171:
172: //- set name
173:
174: pvcResult->pcName = calloc(1 + strlen(pcName), sizeof(char));
175:
176: strcpy(pvcResult->pcName, pcName);
177:
178: //- return result
179:
180: return(pvcResult);
181: }
182:
183:
184: /// **************************************************************************
185: ///
186: /// SHORT: VClampSetFields()
187: ///
188: /// ARGS.:
189: ///
190: /// dInjected.....: injected current.
191: /// dC............: parallel initial capacitance.
192: /// dR............: initial resistance.
193: /// dCommand_init.: initial command voltage.
194: /// dGain.........: gain value.
195: /// dTau_i........: integrating time constant.
196: /// dTau_d........: derivative time constant.
197: /// dSaturation...: saturation value.
198: ///
199: /// RTN..: int
200: ///
201: /// success of operation.
202: ///
203: /// DESCR: set operation fields of voltage clamper.
204: ///
205: /// NOTE.:
206: ///
207: /// The initial command voltage should probably have a separate
208: /// setter method.
209: ///
210: /// **************************************************************************
211:
212: int
213: VClampSetFields
214: (struct VClamp * pvc,
215: double dInjected,
216: double dC,
217: double dR,
218: double dCommand_init,
219: double dGain,
220: double dTau_i,
221: double dTau_d,
222: double dSaturation)
223: {
224: //- set default result: ok
225:
226: int iResult = 1;
227:
228: //- set fields
229:
230: pvc->dInjected = dInjected;
231:
232: pvc->dC = dC;
233: pvc->dR = dR;
234: pvc->dCommand = dCommand_init;
235:
236: pvc->dGain = dGain;
237: pvc->dTau_i = dTau_i;
238: pvc->dTau_d = dTau_d;
239: pvc->dSaturation = dSaturation;
240:
241: //- return result
242:
243: return(iResult);
244: }
245:
246:
247: /// **************************************************************************
248: ///
249: /// SHORT: VClampSingleStep()
250: ///
251: /// ARGS.:
252: ///
253: /// pvc...: voltage clamper.
254: /// dTime.: current simulation time.
255: ///
256: /// RTN..: int
257: ///
258: /// success of operation.
259: ///
260: /// DESCR: Compute new currents to correct voltages.
261: ///
262: /// NOTE.:
263: ///
264: /// Old current values are overwritten.
265: ///
266: /// **************************************************************************
267:
268: int VClampSingleStep(struct VClamp * pvc, double dTime)
269: {
270: //- set default result: ok
271:
272: int iResult = 1;
273:
274: //- calculate the time step
275:
276: double dStep = dTime - pvc->dPreviousTime;
277:
278: //- exponential euler integration for the RC circuit
279:
280: double dA = pvc->dInjected / pvc->dC;
281:
282: double dB = 1 / (pvc->dR * pvc->dC);
283:
284: double dD = exp( - dB * dStep);
285:
286: pvc->dCommand = (pvc->dCommand * dD + (dA / dB) * (1 - dD));
287:
288: //- first preserve the previous value
289:
290: pvc->dEPrevious = pvc->dE;
291:
292: pvc->dE = pvc->dCommand - *pvc->pdVoltage;
293:
294: pvc->dEDerivative = (pvc->dE - pvc->dEPrevious) / dStep;
295:
296: pvc->dEIntegral += 0.5 * (pvc->dE + pvc->dEPrevious) * dStep;
297:
298: //- compute output
299:
300: pvc->dOutput
301: = (pvc->dGain *
302: (pvc->dE
303: + pvc->dTau_d * pvc->dEDerivative
304: + 1 / pvc->dTau_i * pvc->dEIntegral));
305:
306: //- apply saturation
307:
308: if (pvc->dOutput > pvc->dSaturation)
309: {
310: pvc->dOutput = pvc->dSaturation;
311:
312: pvc->dEIntegral -= 0.5 * (pvc->dE + pvc->dEPrevious) * dStep;
313: }
314: else if (pvc->dOutput < - pvc->dSaturation)
315: {
316: pvc->dOutput = - pvc->dSaturation;
317:
318: pvc->dEIntegral -= 0.5 * (pvc->dE + pvc->dEPrevious) * dStep;
319: }
320:
321: //- set the output
322:
323: *pvc->pdInjector = pvc->dOutput;
324:
325: //- register the current simulation time for the next time we are scheduled
326:
327: pvc->dPreviousTime = dTime;
328:
329: //- return result
330:
331: return(iResult);
332: }
333:
334:
335:
Generated by Xrefactory version 2.0.14 on Thu Jul 24 22:41:20 2008