Logo Search packages:      
Sourcecode: gnucap version File versions  Download package

d_diode.cc

/* $Id: d_diode.model,v 23.1 2002/11/06 07:47:50 al Exp $ -*- C++ -*-
 * Copyright (C) 2001 Albert Davis
 * Author: Albert Davis <aldavis@ieee.org>
 *
 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
 *
 * This program 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 program 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 program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *------------------------------------------------------------------
 * diode model.
 * netlist syntax:
 * device:  dxxxx n+ n- mname <area> <off> <ic=vd> <model-card-args>
 * model:   .model mname D <args>
 *
 * The section "eval Yj" is a big mess.
 * It will be redone using multiple files, like the MOS models.
 */
/* This file is automatically generated. DO NOT EDIT */

#include "e_aux.h"
#include "d_admit.h"
#include "d_cap.h"
#include "d_res.h"
  static bool dummy=false;
  enum {USE_OPT = 0x8000};
#include "ap.h"
#include "d_diode.h"
/*--------------------------------------------------------------------------*/
const double NA(NOT_INPUT);
const double INF(BIGBIG);
/*--------------------------------------------------------------------------*/
int MODEL_DIODE::_count = 0;
/*--------------------------------------------------------------------------*/
SDP_DIODE::SDP_DIODE(const COMMON_COMPONENT* cc)
  :SDP_CARD(cc)
{
}
/*--------------------------------------------------------------------------*/
TDP_DIODE::TDP_DIODE(const DEV_DIODE*)
{
}
/*--------------------------------------------------------------------------*/
MODEL_DIODE::MODEL_DIODE()
  :MODEL_CARD(),
   js(1e-14),
   rs(0.0),
   n_factor(1.0),
   tt(0.0),
   cjo(NA),
   pb(NA),
   mj(0.5),
   eg(1.11),
   xti(3.0),
   kf(NA),
   af(NA),
   fc(0.5),
   bv(NA),
   ibv(1e-3),
   cjsw(0.0),
   pbsw(NA),
   mjsw(NA),
   gparallel(0.0),
   flags(USE_OPT),
   mos_level(0)
{
  ++_count;
  _tnom = OPT::tnom;
}
/*--------------------------------------------------------------------------*/
bool MODEL_DIODE::parse_front(CS& cmd)
{
  return ONE_OF
    || set(cmd, "D", &dummy, true)
    ;
}
/*--------------------------------------------------------------------------*/
bool MODEL_DIODE::parse_params(CS& cmd)
{
  return ONE_OF
    || get(cmd, "TNOM", &_tnom, mOFFSET, -ABS_ZERO)
    || get(cmd, "IS", &js, mPOSITIVE)
    || get(cmd, "RS", &rs, mPOSITIVE)
    || get(cmd, "N", &n_factor, mPOSITIVE)
    || get(cmd, "TT", &tt, mPOSITIVE)
    || get(cmd, "CJo", &cjo, mPOSITIVE)
    || get(cmd, "PB", &pb, mPOSITIVE)
    || get(cmd, "VJ", &pb, mPOSITIVE)
    || get(cmd, "Mj", &mj, mPOSITIVE)
    || get(cmd, "EGap", &eg, mPOSITIVE)
    || get(cmd, "XTI", &xti, mPOSITIVE)
    || get(cmd, "KF", &kf, mPOSITIVE)
    || get(cmd, "AF", &af, mPOSITIVE)
    || get(cmd, "FC", &fc, mPOSITIVE)
    || get(cmd, "BV", &bv, mPOSITIVE)
    || get(cmd, "IBV", &ibv, mPOSITIVE)
    || get(cmd, "CJSw", &cjsw, mPOSITIVE)
    || get(cmd, "PBSw", &pbsw, mPOSITIVE)
    || get(cmd, "MJSw", &mjsw, mPOSITIVE)
    || get(cmd, "GParallel", &gparallel)
    || get(cmd, "FLAgs", &flags, mOCTAL)
    ;
}
/*--------------------------------------------------------------------------*/
void MODEL_DIODE::parse_finish()
{
  _tnom = std::max(_tnom, 1.0);
  if (cjo == NA) {
    cjo = 0.0;
  }
  if (pb == NA) {
    pb = 1.0;
  }
  if (pbsw == NA) {
    pbsw = pb;
  }
  if (mjsw == NA) {
    mjsw = 0.33;
  }

      if (bv == 0.) {
      bv = NA;
      }
}
/*--------------------------------------------------------------------------*/
SDP_CARD* MODEL_DIODE::new_sdp(const COMMON_COMPONENT* c)const
{
  assert(c);
  {if (dynamic_cast<const COMMON_DIODE*>(c)) {
    return new SDP_DIODE(c);
  }else{
    return MODEL_CARD::new_sdp(c);
  }}
}
/*--------------------------------------------------------------------------*/
void MODEL_DIODE::print_front(OMSTREAM& o)const
{
  {if (dummy == true) {
    o << "  d";
  }else{
    unreachable();
  }}
}
/*--------------------------------------------------------------------------*/
void MODEL_DIODE::print_params(OMSTREAM& o)const
{
  o << "  tnom=" << _tnom-(-ABS_ZERO);
  o << "  is=" << js;
  o << "  rs=" << rs;
  o << "  n=" << n_factor;
  o << "  tt=" << tt;
  o << "  cjo=" << cjo;
  o << "  pb=" << pb;
  o << "  mj=" << mj;
  o << "  egap=" << eg;
  o << "  xti=" << xti;
  if (kf != NA)
    o << "  kf=" << kf;
  if (af != NA)
    o << "  af=" << af;
  o << "  fc=" << fc;
  if (bv != NA)
    o << "  bv=" << bv;
  if (bv != NA)
    o << "  ibv=" << ibv;
  if (cjsw != 0.)
    o << "  cjsw=" << cjsw;
  if (cjsw != 0.)
    o << "  pbsw=" << pbsw;
  if (cjsw != 0.)
    o << "  mjsw=" << mjsw;
  if (gparallel != 0.)
    o << "  gparallel=" << gparallel;
  if (!(flags & USE_OPT))
    o << "  flags=" << flags;
}
/*--------------------------------------------------------------------------*/
void MODEL_DIODE::print_calculated(OMSTREAM& o)const
{
  o << "";
}
/*--------------------------------------------------------------------------*/
bool MODEL_DIODE::is_valid(const COMMON_COMPONENT* cc)const
{
  return MODEL_CARD::is_valid(cc);
}
/*--------------------------------------------------------------------------*/
void MODEL_DIODE::tr_eval(COMPONENT*)const
{
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
int DEV_DIODE::_count = 0;
int COMMON_DIODE::_count = -1;
static COMMON_DIODE Default_DIODE(CC_STATIC);
/*--------------------------------------------------------------------------*/
COMMON_DIODE::COMMON_DIODE(int c)
  :COMMON_COMPONENT(c),
   area(1.0),
   perim(0.0),
   m(1.0),
   off(false),
   ic(NA),
   is_raw(NA),
   rs_raw(NA),
   cj_raw(NA),
   cjsw_raw(NA),
   gparallel_raw(NA),
   _sdp(0),
   is_adjusted(NA),
   rs_adjusted(NA),
   cj_adjusted(NA),
   cjsw_adjusted(NA),
   gparallel_adjusted(NA)
{
  ++_count;
}
/*--------------------------------------------------------------------------*/
COMMON_DIODE::COMMON_DIODE(const COMMON_DIODE& p)
  :COMMON_COMPONENT(p),
   area(p.area),
   perim(p.perim),
   m(p.m),
   off(p.off),
   ic(p.ic),
   is_raw(p.is_raw),
   rs_raw(p.rs_raw),
   cj_raw(p.cj_raw),
   cjsw_raw(p.cjsw_raw),
   gparallel_raw(p.gparallel_raw),
   _sdp(0),
   is_adjusted(p.is_adjusted),
   rs_adjusted(p.rs_adjusted),
   cj_adjusted(p.cj_adjusted),
   cjsw_adjusted(p.cjsw_adjusted),
   gparallel_adjusted(p.gparallel_adjusted)
{
  ++_count;
}
/*--------------------------------------------------------------------------*/
COMMON_DIODE::~COMMON_DIODE()
{
  --_count;
  delete _sdp;
}
/*--------------------------------------------------------------------------*/
bool COMMON_DIODE::operator==(const COMMON_COMPONENT& x)const
{
  const COMMON_DIODE* p = dynamic_cast<const COMMON_DIODE*>(&x);
  return (p
    && area == p->area
    && perim == p->perim
    && m == p->m
    && off == p->off
    && ic == p->ic
    && is_raw == p->is_raw
    && rs_raw == p->rs_raw
    && cj_raw == p->cj_raw
    && cjsw_raw == p->cjsw_raw
    && gparallel_raw == p->gparallel_raw
    && is_equal(x));
}
/*--------------------------------------------------------------------------*/
void COMMON_DIODE::parse(CS& cmd)
{
  assert(!has_model());
  parse_modelname(cmd);
  if (cmd.is_float()) {
    cmd >> area;
  }
  int here = cmd.cursor();
  do{
    0
    || get(cmd, "Area", &area, mPOSITIVE)
    || get(cmd, "Perim", &perim, mPOSITIVE)
    || get(cmd, "M", &m, mPOSITIVE)
    || get(cmd, "OFF", &off)
    || get(cmd, "IC", &ic)
    || get(cmd, "IS", &is_raw, mPOSITIVE)
    || get(cmd, "Rs", &rs_raw, mPOSITIVE)
    || get(cmd, "Cjo", &cj_raw, mPOSITIVE)
    || get(cmd, "CJSW", &cjsw_raw, mPOSITIVE)
    || get(cmd, "GParallel", &gparallel_raw)
    ;
  }while (cmd.more() && !cmd.stuck(&here));
  cmd.check(bWARNING, "what's this?");
}
/*--------------------------------------------------------------------------*/
void COMMON_DIODE::print(OMSTREAM& o)const
{
  o << "  " << modelname();
  o.setfloatwidth(7);
  o << "  area=" << area;
  if (perim != 0.)
    o << "  perim=" << perim;
  if (m != 1.)
    o << "  m=" << m;
  if (off)
    o << "  off=" << off;
  if (ic != NA)
    o << "  ic=" << ic;
  if (is_raw != NA)
    o << "  is=" << is_raw;
  if (rs_raw != NA)
    o << "  rs=" << rs_raw;
  if (cj_raw != NA)
    o << "  cjo=" << cj_raw;
  if (cjsw_raw != NA)
    o << "  cjsw=" << cjsw_raw;
  if (gparallel_raw != NA)
    o << "  gparallel=" << gparallel_raw;
  o << '\n';
}
/*--------------------------------------------------------------------------*/
void COMMON_DIODE::expand(const COMPONENT* d)
{
  const COMMON_DIODE* c = this;
  const MODEL_DIODE* m = dynamic_cast<const MODEL_DIODE*>(attach_model(d));
  if (!m) {
    error(bERROR, d->long_label() + ": model " + modelname()
          + " is not a diode\n");
  }
  delete _sdp;
  _sdp = m->new_sdp(this);
  assert(_sdp);
  const SDP_DIODE* s = dynamic_cast<const SDP_DIODE*>(_sdp);
  assert(s);
  is_adjusted = ((c->is_raw == NA) ? m->js * c->area : c->is_raw);
  rs_adjusted = ((c->rs_raw == NA) ? m->rs / (c->area+1e-20) : c->rs_raw);
  cj_adjusted = ((c->cj_raw == NA) ? m->cjo * c->area : c->cj_raw);
  cjsw_adjusted = ((c->cjsw_raw == NA) ? m->cjsw * c->perim : c->cjsw_raw);
  gparallel_adjusted = ((c->gparallel_raw == NA)
            ? m->gparallel*c->area : c->gparallel_raw);
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
static EVAL_DIODE_Cj Eval_Cj(CC_STATIC);
void EVAL_DIODE_Cj::tr_eval(ELEMENT* d)const
{
  assert(d);
  DEV_DIODE* p = prechecked_cast<DEV_DIODE*>(d->owner());
  assert(p);
  const COMMON_DIODE* c = prechecked_cast<const COMMON_DIODE*>(p->common());
  assert(c);
  const SDP_DIODE* s = prechecked_cast<const SDP_DIODE*>(c->sdp());
  assert(s);
  const MODEL_DIODE* m = prechecked_cast<const MODEL_DIODE*>(c->model());
  assert(m);

    double& volts = d->_y0.x;
    trace1(d->long_label().c_str(), volts);
    
    double cb;
    {if (c->cj_adjusted != 0.) {
      {if (volts < m->fc * m->pb) {
      cb = c->cj_adjusted / pow(1. - (volts / m->pb),  m->mj);
      }else{
      cb = (c->cj_adjusted / pow(1. - m->fc, 1. + m->mj))
        * (1. - m->fc*(1.+m->mj) + (volts/m->pb)*m->mj);
      }}
    }else{
      cb = 0.;
    }}
    assert(cb >= 0.);
    
    double csw;
    {if (c->cjsw_adjusted != 0.) {
      {if (volts < m->fc * m->pbsw) {
      csw = c->cjsw_adjusted / pow(1. - (volts / m->pbsw),  m->mjsw);
      }else{
      csw = (c->cjsw_adjusted / pow(1. - m->fc, 1. + m->mjsw))
        * (1. - m->fc*(1.+m->mjsw) + (volts/m->pbsw)*m->mjsw);
      }}
    }else{
      csw = 0.;
    }}
    assert(csw >= 0.);
    
    double ctt;
    {if (m->tt != 0.) {
      ctt = p->_gd * m->tt;
    }else{
      ctt = 0.;
    }}
    assert(ctt >= 0.);
    
    trace4("", cb, csw, ctt, cb+csw+ctt);
    d->_y0.f1 = cb + csw + ctt;
    {if (SIM::phase == SIM::pTRAN) {
      const DEV_CAPACITANCE* dd = prechecked_cast<const DEV_CAPACITANCE*>(d);
      double cap = (d->_y0.f1 + dd->_q[1].f1) / 2;
      d->_y0.f0 = (d->_y0.x - dd->_q[1].x) * cap + dd->_q[1].f0;
    }else{
      d->_y0.f0 = d->_y0.x * d->_y0.f1;
    }}
    d->_y0 *= c->m;
    trace3(d->long_label().c_str(), d->_y0.x, d->_y0.f0, d->_y0.f1);
}
/*--------------------------------------------------------------------------*/
static EVAL_DIODE_Yj Eval_Yj(CC_STATIC);
void EVAL_DIODE_Yj::tr_eval(ELEMENT* d)const
{
  assert(d);
  DEV_DIODE* p = prechecked_cast<DEV_DIODE*>(d->owner());
  assert(p);
  const COMMON_DIODE* c = prechecked_cast<const COMMON_DIODE*>(p->common());
  assert(c);
  const SDP_DIODE* s = prechecked_cast<const SDP_DIODE*>(c->sdp());
  assert(s);
  const MODEL_DIODE* m = prechecked_cast<const MODEL_DIODE*>(c->model());
  assert(m);

    assert(m->_tnom > 0);
    FPOLY1& y = d->_y0;
    double volts = y.x;
    double amps  = y.f0;
    trace2(d->long_label().c_str(), volts, amps);
    
    int flags = (m->flags & USE_OPT) ? OPT::diodeflags : m->flags;
    double tempratio = SIM::temp / m->_tnom;
    double vt = KoQ * SIM::temp * m->n_factor;
    region_t oldregion = p->_region;
    p->_isat = c->is_adjusted * pow(tempratio, m->xti)
      * exp((m->eg/vt) *(tempratio-1));
    trace4("", tempratio, vt, oldregion, p->_isat);
    
    if (m->mos_level > 0 || flags & 0040) { // Spice style limiting
      double vcrit = vt * log(vt/(kRT2*p->_isat));
      double vold = d->_y1.f0;
      {if((volts > vcrit) && (std::abs(volts - vold) > (vt + vt))) {
      {if(vold > 0) {
        double arg = 1 + (volts - vold) / vt;
        {if(arg > 0) {
          volts = vold + vt * log(arg);
        }else{
          volts = vcrit;
        }}
      }else{
        volts = vt *log(volts/vt);
      }}
      }else{
      // leave volts as is
      }}
    }
    
    {if (m->mos_level > 0 && m->mos_level < 8) {
      switch (m->mos_level) {
      case 1:
      case 2:
      case 3:
      case 6:
      case 4:
      case 5:
      {if (volts <= 0.) {
        p->_region = REVERSE;
        y.f1 = p->_isat / vt + OPT::gmin;
        y.f0 = y.f1 * volts;
      }else{
        p->_region = FORWARD;
        double ev = exp(volts/vt);
        y.f1 = p->_isat * ev / vt + OPT::gmin;
        y.f0 = p->_isat * (ev - 1) + OPT::gmin * volts;
      }}
      break;
      case 7:
      {if (volts < .5) {
        p->_region = REVERSE;
        double ev = exp(volts/vt);
        y.f1 = p->_isat * ev / vt + OPT::gmin;
        y.f0 = p->_isat * (ev - 1) + OPT::gmin * volts;
      }else{
        p->_region = FORWARD;
        double ev = exp(.5/vt);
        double t0 = p->_isat * ev / vt;
        y.f1 = t0 + OPT::gmin;
        y.f0 = p->_isat * (ev - 1) + t0 * (volts - .5) + OPT::gmin * volts;
      }}
      break;
      default:
      unreachable();
      y.f1 = OPT::gmin;
      y.f0 = volts * y.f1;
      }
    }else if (flags & 0040) { // exact Spice model
      {if (volts >= -3*vt) { // forward and weak reversed
      double evd = exp(volts/vt);
      y.f0 = p->_isat * (evd-1);
      y.f1 = p->_isat * evd/vt;
      }else if (m->bv == NA || volts >= m->bv) {
      double arg = 3 * vt / (volts * kE); // strong reversed
      arg = arg * arg * arg;
      y.f0 = -p->_isat * (1+arg);
      y.f1 = p->_isat * 3 * arg / volts;
      }else{
      incomplete();
      double evrev = exp(-(m->bv+volts)/vt);
      y.f0 = -p->_isat * evrev;
      y.f1 = p->_isat * evrev / vt;
      }}
      y.f0 += OPT::gmin * volts;
      y.f1 += OPT::gmin;
    }else{
      {if (c->off  &&  STATUS::iter[SIM::mode] <= 1) { /*initially guess off*/
      p->_region = INITOFF;
      y.f1 = 0.;
      y.f0 = 0.;
      if (flags & 0020) {
        untested();
        y.f1 = OPT::gmin;
      }
      trace2("initoff", y.f0, y.f1);
      }else if (volts <= 0. /* &&  amps < 0.*/) {       /* reverse biased */
      p->_region = REVERSE;                 /* x = volts, f(x) = amps */
      {if (flags & 0010) {
        untested();
        y.f1 = y.f0 = 0.;
      }else{
        double expterm = p->_isat * exp(volts/vt);    
        y.f0 = expterm - p->_isat;/* i = f(x) = _isat * (exp(volts/vt)-1) */
        y.f1 = expterm / vt;      /* f'(x) = (_isat/vt) * exp(volts/vt)   */
      }}
      
      if (flags & 0002) {     // g = gmin, maintain actual current
        y.f1 += OPT::gmin;    // 3 is a resistor, R=1/gmin
        y.f0 += OPT::gmin * volts;
      }
      if (flags & 0004) {     // 5 is a resistor, R=vt/_isat
        double x = p->_isat / vt;
        y.f1 += x;
        y.f0 += x * volts;
      }
      if (flags & 0001) {
        //y.f0 = y.f1 * volts;      // a resistor, R=1/f1
      }
      
      trace2("reverse", y.f0, y.f1);
      }else if (volts >= 0.  &&  amps >= 0.) {          /* forward biased */
                            /* x = amps, f(x) = volts */
      /* derivation: */     /* if f(x) = log(u): f'(x)=(1/u)(du/dx) */
      /* poly1 r; */
      /* r.f0 = vt * log(amps/p->_isat +1.); */
      /* r.f1 = vt / (_isat + amps); */
      /* y.f1 = 1. / r.f1; */
      /* y.f0 = amps - r.f0*y.f1 + volts*y.f1; */
      
      p->_region = FORWARD;
      y.f1 = (p->_isat + amps) / vt;
      y.f0 = amps - log(amps/p->_isat +1.)*(p->_isat + amps) + volts*y.f1;
      trace2("forward", y.f0, y.f1);
      }else{                      /* non-converged, inconsistent      */
      p->_region = UNKNOWN;       /* volts and amps have different signs  */
      y.f1 = p->_isat/vt;         /* guess that the voltage should be 0   */
      y.f0 = 0.;            /* (it usually is very close)       */
      if (flags & 0001) {         /* use the correct value there      */
        y.f0 = volts * y.f1;
      }
      trace2("unknown", y.f0, y.f1);
      }}
      y.f1 += c->gparallel_adjusted;
      y.f0 += c->gparallel_adjusted * volts;
      
      if (oldregion != p->_region  &&  OPT::dampstrategy & dsDEVLIMIT) {
      SIM::fulldamp = true;
      error(bTRACE, p->long_label() + ":device limit damp\n");
      }
      if (flags & 0100) {           // twist g to guarantee g >= gmin
      {if (y.f1 < OPT::gmin) {      // without changing i
        y.f1 = OPT::gmin;
        untested();
      }else{
        untested();
      }}
      }
      if (flags & 0200) {           // add a gmin in parallel
      y.f1 += OPT::gmin;
      y.f0 += OPT::gmin * volts;
      untested();
      }
      if (flags & 0400) {           // linearize .. shift I to pass thru 0
      untested();
      y.f0 = y.f1 * volts;
      }
    }}
    y *= c->m;
    trace3(d->long_label().c_str(), y.x, y.f0, y.f1);
    p->_gd = y.f1;
}
/*--------------------------------------------------------------------------*/
DEV_DIODE::DEV_DIODE()
  :BASE_SUBCKT(),
   _region(UNKNOWN),
   _gd(NA),
   _isat(NA),
   _Cj(0),
   _Yj(0),
   _Rs(0)
{
  _n = _nodes + int_nodes();
  attach_common(&Default_DIODE);
  ++_count;
}
/*--------------------------------------------------------------------------*/
DEV_DIODE::DEV_DIODE(const DEV_DIODE& p)
  :BASE_SUBCKT(p),
   _region(p._region),
   _gd(p._gd),
   _isat(p._isat),
   _Cj(0),
   _Yj(0),
   _Rs(0)
{
  _n = _nodes + int_nodes();
  for (int ii = -int_nodes(); ii < max_nodes(); ++ii) {
    _n[ii] = p._n[ii];
  }
  ++_count;
}
/*--------------------------------------------------------------------------*/
void DEV_DIODE::parse(CS& cmd)
{
  assert(has_common());
  COMMON_DIODE* c = prechecked_cast<COMMON_DIODE*>(common()->clone());
  assert(c);

  parse_Label(cmd);
  parse_nodes(cmd, max_nodes(), min_nodes());
  c->parse(cmd);
  attach_common(c);
}
/*--------------------------------------------------------------------------*/
void DEV_DIODE::print(OMSTREAM& o, int)const
{
  const COMMON_DIODE* c = prechecked_cast<const COMMON_DIODE*>(common());
  assert(c);

  o << short_label();
  printnodes(o);
  c->print(o);
}
/*--------------------------------------------------------------------------*/
void DEV_DIODE::expand()
{
  COMMON_DIODE* c = prechecked_cast<COMMON_DIODE*>(mutable_common());
  assert(c);
  c->expand(this);
  const MODEL_DIODE* m = prechecked_cast<const MODEL_DIODE*>(c->model());
  assert(m);
  const SDP_DIODE* s = prechecked_cast<const SDP_DIODE*>(c->sdp());
  assert(s);

  {if (!OPT::rstray || c->rs_adjusted==0.) {
    _n[n_ianode] = _n[n_anode];
  }else{
    _n[n_ianode].new_model_node();
  }}

  {if (c->cj_adjusted == 0. && c->cjsw_adjusted == 0. && m->tt == 0.) {
    if (_Cj) {
      subckt().erase(_Cj);
      _Cj = NULL;
    }
  }else{
    if (!_Cj) {
      _Cj = new DEV_CAPACITANCE;
      subckt().push_front(_Cj);
    }
    {{
      node_t nodes[] = {_n[n_ianode], _n[n_cathode]};
      _Cj->set_parameters("Cj", this, &Eval_Cj, 0., 0, 0, 2, nodes);
    }}
  }}
  {{
    if (!_Yj) {
      _Yj = new DEV_ADMITTANCE;
      subckt().push_front(_Yj);
    }
    {{
      node_t nodes[] = {_n[n_ianode], _n[n_cathode]};
      _Yj->set_parameters("Yj", this, &Eval_Yj, 0., 0, 0, 2, nodes);
    }}
  }}
  {if (!OPT::rstray || c->rs_adjusted==0.) {
    if (_Rs) {
      subckt().erase(_Rs);
      _Rs = NULL;
    }
  }else{
    if (!_Rs) {
      _Rs = new DEV_RESISTANCE;
      subckt().push_front(_Rs);
    }
    {{
      node_t nodes[] = {_n[n_anode], _n[n_ianode]};
      _Rs->set_parameters("Rs", this, NULL, c->rs_adjusted/c->m, 0, 0, 2, nodes);
    }}
  }}
  assert(subckt().exists());
  subckt().expand();
  assert(!constant());
}
/*--------------------------------------------------------------------------*/
double DEV_DIODE::tr_probe_num(CS& cmd)const
{
  const COMMON_DIODE* c = prechecked_cast<const COMMON_DIODE*>(common());
  assert(c);
  const MODEL_DIODE* m = prechecked_cast<const MODEL_DIODE*>(c->model());
  assert(m);
  const SDP_DIODE* s = prechecked_cast<const SDP_DIODE*>(c->sdp());
  assert(s);

  {if (cmd.pmatch("Vd")) {
    return  _n[n_anode].v0() - _n[n_cathode].v0();
  }else if (cmd.pmatch("Id")) {
    return  CARD::probe(_Yj,"I") + CARD::probe(_Cj,"I");
  }else if (cmd.pmatch("VJ")) {
    return  _n[n_ianode].v0() - _n[n_cathode].v0();
  }else if (cmd.pmatch("VSR")) {
    return  _n[n_anode].v0() - _n[n_ianode].v0();
  }else if (cmd.pmatch("VRS")) {
    return  _n[n_anode].v0() - _n[n_ianode].v0();
  }else if (cmd.pmatch("IJ")) {
    return  CARD::probe(_Yj,"I");
  }else if (cmd.pmatch("IC")) {
    return  CARD::probe(_Cj,"I");
  }else if (cmd.pmatch("CAPCUR")) {
    return  CARD::probe(_Cj,"I");
  }else if (cmd.pmatch("P")) {
    return  CARD::probe(_Yj,"P") + CARD::probe(_Cj,"P") + CARD::probe(_Rs,"P");
  }else if (cmd.pmatch("PD")) {
    return  CARD::probe(_Yj,"PD") + CARD::probe(_Cj,"PD") + CARD::probe(_Rs,"PD");
  }else if (cmd.pmatch("PS")) {
    return  CARD::probe(_Yj,"PS") + CARD::probe(_Cj,"PS") + CARD::probe(_Rs,"PS");
  }else if (cmd.pmatch("PJ")) {
    return  CARD::probe(_Yj,"P");
  }else if (cmd.pmatch("PC")) {
    return  CARD::probe(_Cj,"P");
  }else if (cmd.pmatch("Capacitance")) {
    return  CARD::probe(_Cj,"Capacitance");
  }else if (cmd.pmatch("CD")) {
    return  CARD::probe(_Cj,"Capacitance");
  }else if (cmd.pmatch("CHARGE")) {
    return  CARD::probe(_Cj,"Charge");
  }else if (cmd.pmatch("Req")) {
    return  CARD::probe(_Yj,"R") + CARD::probe(_Rs,"R");
  }else if (cmd.pmatch("Geq")) {
    return  (( CARD::probe(_Yj,"R") + CARD::probe(_Rs,"R") ) != 0) ? (1./( CARD::probe(_Yj,"R") + CARD::probe(_Rs,"R") )) : CARD::probe(_Yj,"Y");
  }else if (cmd.pmatch("GD")) {
    return  CARD::probe(_Yj,"Y");
  }else if (cmd.pmatch("Y")) {
    return  ( CARD::probe(_Rs,"R") != 0. && ( CARD::probe(_Yj,"Y") + CARD::probe(_Cj,"Y") ) != 0) ? 1./((1./( CARD::probe(_Yj,"Y") + CARD::probe(_Cj,"Y") )) + CARD::probe(_Rs,"R") ) : CARD::probe(_Yj,"Y") + CARD::probe(_Cj,"Y");
  }else if (cmd.pmatch("Z")) {
    return  port_impedance( _n[n_anode] , _n[n_cathode] ,lu,tr_probe_num_str("Y"));
  }else if (cmd.pmatch("ZRAW")) {
    return  port_impedance( _n[n_anode] , _n[n_cathode] , lu, 0.);
  }else if (cmd.pmatch("REgion")) {
    return  static_cast<double>(_region);
  }else {
    return BASE_SUBCKT::tr_probe_num(cmd);
  }}
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

Generated by  Doxygen 1.6.0   Back to index