* tswitch.cpp - time controlled switch class implementation
*
* Copyright (C) 2006, 2008 Stefan Jahn <stefan@lkcc.org>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $Id$
*
*/
* \file tswitch.cpp
* \brief time controlled switch class implementation
*
* \todo add a property to allow choosing the resistance profile
* (cubic spline, linear, abrupt)
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <iostream>
#include <cmath>
#include "component.h"
#include "tswitch.h"
using namespace qucs;
tswitch::tswitch () : circuit (2) {
type = CIR_TSWITCH;
setVoltageSources (1);
}
nr_double_t tswitch::initState (void) {
const char * const init = getPropertyString ("init");
bool on = !strcmp (init, "on");
return on ? getPropertyDouble ("Ron") : getPropertyDouble ("Roff");
}
void tswitch::initSP (void) {
nr_double_t r = initState ();
allocMatrixS ();
setS (NODE_1, NODE_1, r / (r + 2));
setS (NODE_2, NODE_2, r / (r + 2));
setS (NODE_1, NODE_2, 2 / (r + 2));
setS (NODE_2, NODE_1, 2 / (r + 2));
}
void tswitch::calcNoiseSP (nr_double_t) {
nr_double_t T = getPropertyDouble ("Temp");
nr_double_t r = initState ();
nr_double_t f = celsius2kelvin (T) * 4.0 * r * z0 / sqr (2.0 * z0 + r) / T0;
setN (NODE_1, NODE_1, +f); setN (NODE_2, NODE_2, +f);
setN (NODE_1, NODE_2, -f); setN (NODE_2, NODE_1, -f);
}
void tswitch::calcNoiseAC (nr_double_t) {
nr_double_t r = initState ();
if (r > 0.0 || r < 0.0) {
nr_double_t T = getPropertyDouble ("Temp");
nr_double_t f = celsius2kelvin (T) / T0 * 4.0 / r;
setN (NODE_1, NODE_1, +f); setN (NODE_2, NODE_2, +f);
setN (NODE_1, NODE_2, -f); setN (NODE_2, NODE_1, -f);
}
}
void tswitch::initDC (void) {
nr_double_t r = initState ();
allocMatrixMNA ();
voltageSource (VSRC_1, NODE_1, NODE_2);
setD (VSRC_1, VSRC_1, -r);
}
void tswitch::initAC (void) {
initDC ();
}
void tswitch::initTR (void) {
qucs::vector * values = getPropertyVector ("time");
T = real (sum (*values));
repeat = (values->getSize () % 2) == 0 ? true : false;
nr_double_t maxduration = getPropertyDouble("MaxDuration");
duration = std::min ( std::max (10*NR_TINY, values->minimum() / 100),
maxduration );
initDC ();
}
void tswitch::calcTR (nr_double_t t) {
const char * const init = getPropertyString ("init");
nr_double_t ron = getPropertyDouble ("Ron");
nr_double_t roff = getPropertyDouble ("Roff");
const char * const trans_type = getPropertyString ("Transition");
nr_double_t r = 0;
nr_double_t rdiff = 0;
nr_double_t r_0 = 0;
qucs::vector * values = getPropertyVector ("time");
bool on = !strcmp (init, "on");
nr_double_t ti = 0;
if (repeat) {
t = t - T * qucs::floor (t / T);
}
nr_double_t ts = -2*duration;
for (int i = 0; i < values->getSize (); i++) {
ti += real (values->get (i));
if (t >= ti)
{
on = !on;
ts = ti;
}
else {
break;
}
}
if (!strcmp(trans_type, "abrupt")) {
r = (on ? ron : roff);
} else {
nr_double_t tdiff = std::max(NR_TINY, t - ts);
if (tdiff > duration) {
tdiff = duration;
}
if (on) {
r_0 = roff;
rdiff = ron - roff;
} else {
r_0 = ron;
rdiff = roff - ron;
}
if (!strcmp(trans_type, "linear")) {
r = r_0 + rdiff * tdiff / duration;
} else {
r = r_0 + (((-2. * rdiff * tdiff / duration) + 3. * rdiff) * qucs::pow(tdiff/duration, 2.0));
}
}
assert(r >= ron);
assert(r <= roff);
setD (VSRC_1, VSRC_1, -r);
}
PROP_REQ [] = {
{ "init", PROP_STR, { PROP_NO_VAL, "off" }, PROP_RNG_STR2 ("on", "off") },
{ "time", PROP_LIST, { 1e-9, PROP_NO_STR }, PROP_POS_RANGE },
PROP_NO_PROP };
PROP_OPT [] = {
{ "Ron", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
{ "Roff", PROP_REAL, { 1e12, PROP_NO_STR }, PROP_POS_RANGE },
{ "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
{ "MaxDuration", PROP_REAL, { 1e-6, PROP_NO_STR }, PROP_MIN_VAL (10*NR_TINY) },
{ "Transition", PROP_STR, { PROP_NO_VAL, "spline" }, PROP_RNG_STR3 ("abrupt", "linear", "spline") },
PROP_NO_PROP };
struct define_t tswitch::cirdef =
{ "Switch", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };