MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
VClamp.cpp
Go to the documentation of this file.
1 // VClamp.cpp ---
2 //
3 // Filename: VClamp.cpp
4 // Description:
5 // Author:
6 // Maintainer:
7 // Created: Fri Feb 1 19:30:45 2013 (+0530)
8 // Version:
9 // Last-Updated: Tue Jun 11 17:33:16 2013 (+0530)
10 // By: subha
11 // Update #: 297
12 // URL:
13 // Keywords:
14 // Compatibility:
15 //
16 //
17 
18 // Commentary:
19 //
20 // Implementation of Voltage Clamp
21 //
22 //
23 
24 // Change log:
25 //
26 //
27 //
28 //
29 // This program is free software; you can redistribute it and/or
30 // modify it under the terms of the GNU Lesser General Public License as
31 // published by the Free Software Foundation; either version 3, or
32 // (at your option) any later version.
33 //
34 // This program is distributed in the hope that it will be useful,
35 // but WITHOUT ANY WARRANTY; without even the implied warranty of
36 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 // Lesser General Public License for more details.
38 //
39 // You should have received a copy of the GNU Lesser General Public License
40 // along with this program; see the file COPYING. If not, write to
41 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth
42 // Floor, Boston, MA 02110-1301, USA.
43 //
44 //
45 
46 // Code:
47 
48 #include "header.h"
49 #include "Dinfo.h"
50 #include "VClamp.h"
51 
52 using namespace moose;
53 
54 const unsigned int VClamp::DERIVATIVE_ON_PV = 1;
55 const unsigned int VClamp::PROPORTIONAL_ON_PV = 2;
56 
57 
59 {
60  static SrcFinfo1< double > currentOut("currentOut",
61  "Sends out current output of the clamping circuit. This should be"
62  " connected to the `injectMsg` field of a compartment to voltage clamp"
63  " it.");
64  return &currentOut;
65 }
66 
67 
69 {
70  static DestFinfo process("process",
71  "Handles 'process' call on each time step.",
73  static DestFinfo reinit("reinit",
74  "Handles 'reinit' call",
76  static Finfo * processShared[] = {
77  &process,
78  &reinit
79  };
80 
81  static SharedFinfo proc("proc",
82  "Shared message to receive Process messages from the scheduler",
83  processShared, sizeof(processShared) / sizeof(Finfo*));
84 
85  static ValueFinfo< VClamp, double> command("command",
86  "Command input received by the clamp circuit.",
89  static ValueFinfo< VClamp, unsigned int> mode("mode",
90  "Working mode of the PID controller.\n"
91  "\n"
92  " mode = 0, standard PID with proportional, integral and derivative"
93  " all acting on the error.\n"
94  "\n"
95  " mode = 1, derivative action based on command input\n"
96  "\n"
97  " mode = 2, proportional action and derivative action are based on"
98  " command input.",
100  &VClamp::getMode);
101  static ValueFinfo< VClamp, double> ti("ti",
102  "Integration time of the PID controller. Defaults to 1e9, i.e. integral"
103  " action is negligibly small.",
104  &VClamp::setTi,
105  &VClamp::getTi);
106 
107  static ValueFinfo< VClamp, double> td("td",
108  "Derivative time of the PID controller. This defaults to 0,"
109  "i.e. derivative action is unused.",
110  &VClamp::setTd,
111  &VClamp::getTd);
112  static ValueFinfo< VClamp, double> tau("tau",
113  "Time constant of the lowpass filter at input of the PID"
114  " controller. This smooths out abrupt changes in the input. Set it to "
115  " 5 * dt or more to avoid overshoots.",
117  &VClamp::getTau);
118  static ValueFinfo< VClamp, double> gain("gain",
119  "Proportional gain of the PID controller.",
121  &VClamp::getGain);
122  static ReadOnlyValueFinfo< VClamp, double> current("current",
123  "The amount of current injected by the clamp into the membrane.",
125 
126 
127  static ReadOnlyValueFinfo<VClamp, double> sensed("sensed",
128  "Membrane potential read from compartment.",
129  &VClamp::getVin);
130  static DestFinfo sensedIn("sensedIn",
131  "The `VmOut` message of the Compartment object should be connected"
132  " here.",
134 
135  static DestFinfo commandIn("commandIn",
136  " The command voltage source should be connected to this.",
138 
139  static Finfo* vclampFinfos[] = {
140  currentOut(),
141  &command,
142  &current,
143  &sensed,
144  &mode,
145  &ti,
146  &td,
147  &tau,
148  &gain,
149  &sensedIn,
150  &commandIn,
151  &proc
152  };
153 
154  static string doc[] = {
155  "Name", "VClamp",
156  "Author", "Subhasis Ray",
157  "Description", "Voltage clamp object for holding neuronal compartments at a specific"
158  " voltage.\n"
159  "\n"
160  "This implementation uses a builtin RC circuit to filter the "
161  " command input and then use a PID to bring the sensed voltage (Vm from"
162  " compartment) to the filtered command potential.\n"
163  "\n"
164  "Usage: Connect the `currentOut` source of VClamp to `injectMsg`"
165  " dest of Compartment. Connect the `VmOut` source of Compartment to"
166  " `set_sensed` dest of VClamp. Either set `command` field to a"
167  " fixed value, or connect an appropriate source of command potential"
168  " (like the `outputOut` message of an appropriately configured"
169  " PulseGen) to `set_command` dest.\n"
170  "The default settings for the RC filter and PID controller should be"
171  " fine. For step change in command voltage, good defaults with"
172  "integration time step dt are as follows:\n"
173  " time constant of RC filter, tau = 5 * dt\n"
174  " proportional gain of PID, gain = Cm/dt where Cm is the membrane"
175  " capacitance of the compartment\n"
176  " integration time of PID, ti = dt\n"
177  " derivative time of PID, td = 0\n"
178  "\n",
179  };
180 
181  static Dinfo< VClamp > dinfo;
182  static Cinfo vclampCinfo(
183  "VClamp",
185  vclampFinfos,
186  sizeof(vclampFinfos) / sizeof(Finfo*),
187  &dinfo,
188  doc,
189  sizeof(doc)/sizeof(string));
190 
191  return &vclampCinfo;
192 }
193 
195 
196 VClamp::VClamp(): vIn_(0.0), command_(0.0), current_(0.0), mode_(0), ti_(0.0), td_(-1.0),
197  Kp_(0.0),
198  tau_(0.0),
199  tdByDt_(1.0),
200  dtByTi_(1.0),
201  e_(0.0),
202  e1_(0.0),
203  e2_(0.0)
204 {
205 }
206 
208 {
209  ;
210 }
211 
213 {
214  cmdIn_ = value;
215 }
216 
217 double VClamp::getCommand() const
218 {
219  return cmdIn_;
220 }
221 
222 void VClamp::setTi(double value)
223 {
224  ti_ = value;
225 }
226 
227 double VClamp::getTi() const
228 {
229  return ti_;
230 }
231 void VClamp::setTd(double value)
232 {
233  td_ = value;
234 }
235 
236 double VClamp::getTd() const
237 {
238  return td_;
239 }
240 
241 void VClamp::setTau(double value)
242 {
243  tau_ = value;
244 }
245 
246 double VClamp::getTau() const
247 {
248  return tau_;
249 }
250 
251 void VClamp::setGain(double value)
252 {
253  Kp_ = value;
254 }
255 
256 double VClamp::getGain() const
257 {
258  return Kp_;
259 }
260 
261 double VClamp::getCurrent() const
262 {
263  return current_;
264 }
265 
266 void VClamp::setVin(double value)
267 {
268  vIn_ = value;
269 }
270 
271 double VClamp::getVin() const
272 {
273  return vIn_;
274 }
275 
276 
277 void VClamp::setMode(unsigned int mode)
278 {
279  mode_ = mode;
280 }
281 
282 unsigned int VClamp::getMode() const
283 {
284  return mode_;
285 }
286 
287 void VClamp::process(const Eref& e, ProcPtr p)
288 {
289  assert(ti_ > 0);
290  assert(td_ >= 0);
291  assert(tau_ > 0);
292  double dCmd = cmdIn_ - oldCmdIn_;
293  command_ = cmdIn_ + dCmd * ( 1 - tauByDt_) + (command_ - cmdIn_ + dCmd * tauByDt_) * expt_;
294  oldCmdIn_ = cmdIn_;
295  e_ = command_ - vIn_;
296  if (mode_ == 0){
297  current_ += Kp_ * ((1 + dtByTi_ + tdByDt_) * e_ - ( 1 + 2 * tdByDt_) * e1_ + tdByDt_ * e2_);
298  e2_ = e1_;
299  e1_ = e_;
300  } else if (mode_ == DERIVATIVE_ON_PV){ // Here the derivative error term is replaced by process variable
301  current_ += Kp_ * ((1 + dtByTi_) * e_ - e1_ + tdByDt_ * ( vIn_ - 2 * v1_ + e2_));
302  e2_ = v1_;
303  v1_ = vIn_;
304  e1_ = e_;
305  } else if (mode_ == PROPORTIONAL_ON_PV){ // Here the proportional as well as the derivative error term is replaced by process variable
306  current_ += Kp_ * (vIn_ - v1_ + dtByTi_ * e_ + tdByDt_ * ( vIn_ - 2 * v1_ + e2_));
307  e2_ = v1_;
308  v1_ = vIn_;
309  }
310  currentOut()->send(e, current_);
311 }
312 
313 void VClamp::reinit(const Eref& e, ProcPtr p)
314 {
315 
316  vIn_ = 0.0;
317  v1_ = 0;
318  command_ = cmdIn_ = oldCmdIn_ = e_ = e1_ = e2_ = 0;
319  if (ti_ == 0){
320  ti_ = p->dt;
321  }
322  if (td_ < 0){
323  td_ = 0.0;
324  }
325  if (tau_ == 0.0){
326  tau_ = 5 * p->dt;
327  }
328  if (p->dt / tau_ > 1e-15){
329  expt_ = exp(-p->dt/tau_);
330  } else {
331  expt_ = 1 - p->dt/tau_;
332  }
333  tauByDt_ = tau_ / p->dt;
334  dtByTi_ = p->dt/ti_;
335  tdByDt_ = td_ / p->dt;
336 
337  vector<Id> compartments;
338  unsigned int numComp = e.element()->getNeighbors(compartments, currentOut());
339  if (numComp > 0){
340  double Cm = Field<double>::get(compartments[0], "Cm");
341  if (Kp_ == 0){
342  Kp_ = Cm / p->dt;
343  }
344  command_ = cmdIn_ = oldCmdIn_ =
345  Field<double>::get(compartments[0], "initVm");
346  }
347 }
348 
349 //
350 // VClamp.cpp ends here
void reinit(const Eref &e, ProcPtr p)
Definition: VClamp.cpp:313
unsigned int getMode() const
Definition: VClamp.cpp:282
double getVin() const
Definition: VClamp.cpp:271
uint32_t value
Definition: moosemodule.h:42
void setTau(double value)
Definition: VClamp.cpp:241
static SrcFinfo1< double > * currentOut()
Definition: VClamp.cpp:58
void setVin(double v)
Definition: VClamp.cpp:266
static const Cinfo * vclampCinfo
Definition: VClamp.cpp:194
double tau_
Definition: VClamp.h:91
Definition: Dinfo.h:60
double dtByTi_
Definition: VClamp.h:93
double ti_
Definition: VClamp.h:88
Element * element() const
Definition: Eref.h:42
double vIn_
Definition: VClamp.h:82
double tauByDt_
Definition: VClamp.h:94
double e2_
Definition: VClamp.h:97
double getTd() const
Definition: VClamp.cpp:236
void setTd(double value)
Definition: VClamp.cpp:231
static const unsigned DERIVATIVE_ON_PV
Definition: VClamp.h:53
double command_
Definition: VClamp.h:83
double getTau() const
Definition: VClamp.cpp:246
double dt
Definition: ProcInfo.h:18
unsigned int mode_
Definition: VClamp.h:85
double oldCmdIn_
Definition: VClamp.h:100
void setMode(unsigned int mode)
Definition: VClamp.cpp:277
double v1_
Definition: VClamp.h:98
double tdByDt_
Definition: VClamp.h:92
void setCommand(double v)
Definition: VClamp.cpp:212
Definition: OpFunc.h:27
Definition: Eref.h:26
void setGain(double value)
Definition: VClamp.cpp:251
double e_
Definition: VClamp.h:95
double td_
Definition: VClamp.h:89
double Kp_
Definition: VClamp.h:90
double getTi() const
Definition: VClamp.cpp:227
double expt_
Definition: VClamp.h:101
double cmdIn_
Definition: VClamp.h:99
void process(const Eref &e, ProcPtr p)
Definition: VClamp.cpp:287
double getCurrent() const
Definition: VClamp.cpp:261
unsigned int getNeighbors(vector< Id > &ret, const Finfo *finfo) const
Definition: Element.cpp:949
double e1_
Definition: VClamp.h:96
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
double current_
Definition: VClamp.h:84
void setTi(double value)
Definition: VClamp.cpp:222
double getCommand() const
Definition: VClamp.cpp:217
static const Cinfo * initCinfo()
Definition: VClamp.cpp:68
static const unsigned PROPORTIONAL_ON_PV
Definition: VClamp.h:54
Definition: Cinfo.h:18
double getGain() const
Definition: VClamp.cpp:256
Definition: Finfo.h:12