/* $Id: d_bjt.model,v 25.92 2006/06/28 15:02:53 al Exp $ -*- C++ -*-
 * Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *------------------------------------------------------------------
 * Berkeley BJT model
 * Derived from Spice code, both from 2g6 and 3f4
 * Recoded for Gnucap model compiler, Al Davis, 2002
 *------------------------------------------------------------------
 * data structures and defaults for bjt model.
 *
 * netlist syntax:
 * device:  qxxxx c b e s mname <device args>
 * model:   .model mname NPN <args>
 *	or  .model mname PNP <args>
 *
 * known BUGs
 * 1. excess phase partially implemented, disabled, as if PTF == 0.
 */
/* This file is automatically generated. DO NOT EDIT */

#include "u_limit.h"
#include "d_admit.h"
#include "d_cap.h"
#include "d_res.h"
#include "ap.h"
#include "d_bjt.h"
/*--------------------------------------------------------------------------*/
const double NA(NOT_INPUT);
const double INF(BIGBIG);
/*--------------------------------------------------------------------------*/
int MODEL_BJT::_count = 0;
/*--------------------------------------------------------------------------*/
SDP_BJT::SDP_BJT(const COMMON_COMPONENT* cc)
  :SDP_DIODE(cc)
{
}
/*--------------------------------------------------------------------------*/
TDP_BJT::TDP_BJT(const DEV_BJT* d)
{
  assert(d);
  const COMMON_BJT* c = prechecked_cast<const COMMON_BJT*>(d->common());
  assert(c);
  const SDP_BJT* s = prechecked_cast<const SDP_BJT*>(c->sdp());
  assert(s);
  const MODEL_BJT* m = prechecked_cast<const MODEL_BJT*>(c->model());
  assert(m);
    // final adjust: code_pre

      const double reftemp = 300.15;
      double temp = (c->temp != NA) ? c->temp : SIM::temp_c + P_CELSIUS0;
      double fact1 = m->tnom_k / reftemp;
      double fact2 = temp / reftemp;
      double tempratio  = temp / m->tnom_k; // fact2/fact1
      double kt = temp * P_K;
      vt = temp * P_K_Q;
      double egap = 1.16 - (7.02e-4*temp*temp) / (temp+1108.); // egfet
      // double arg = (m->eg*tempratio - egap) / (2*kt);
      double arg = -egap/(2 * kt) + 1.1150877 / (P_K * (reftemp+reftemp));
      double pbfact = -2 * vt * (1.5 * log(fact2) + P_Q * arg);
      double ratlog = log(tempratio);
      double ratio1 = tempratio - 1;
      double factlog = ratio1 * m->eg / vt + m->xti * ratlog;
      double factor = exp(factlog);
      double bfactor = exp(ratlog * m->xtb);

    // final adjust: override
    // final adjust: raw
    // final adjust: mid
    // final adjust: calculated
    ibc = m->ibc * factor;
    ibe = m->ibe * factor;
    BetaF = m->bf * bfactor;
    BetaR = m->br * bfactor;
    BEleakCur = m->ise * exp(factlog/m->ne) / bfactor;
    BCleakCur = m->isc * exp(factlog/m->nc) / bfactor;
    Vcrit = vt * log(vt / (M_SQRT2 * m->ibe));
    // final adjust: post

      {
	double pbo = (m->vje - pbfact) / fact1;
	BEpot = fact2 * pbo + pbfact;
	double gmaold = (m->vje - pbo) / pbo;
	double gmanew = (BEpot - pbo) / pbo;
	BEcap = (m->cje / (1 + m->mje * (4e-4*(m->tnom_k-reftemp)-gmaold)))
	  * (1 + m->mje * (4e-4*(temp-reftemp)-gmanew));
	DepCap = m->fc * BEpot;
	f1 = BEpot * (1 - exp((1 - m->mje) * m->xfc)) / (1 - m->mje);
      }
      {
	double pbo = (m->vjc - pbfact) / fact1;
	BCpot = fact2 * pbo + pbfact;
	double gmaold = (m->vjc - pbo) / pbo;
	double gmanew = (BCpot - pbo) / pbo;
	BCcap = (m->cjc / (1 + m->mjc 
			   * (4e-4*(m->tnom_k-reftemp)-gmaold)))
	  * (1 + m->mjc * (4e-4*(temp-reftemp)-gmanew));
	f4 = m->fc * BCpot;
	f5 = BCpot * (1 - exp((1 - m->mjc) * m->xfc)) / (1 - m->mjc);
      }
    // final adjust: done
}
/*--------------------------------------------------------------------------*/
MODEL_BJT::MODEL_BJT()
  :MODEL_DIODE(),
   level(1),
   bf(100),
   br(1),
   ibc(NA),
   ibe(NA),
   is(NA),
   nf(1),
   nr(1),
   vaf(NA),
   var(NA),
   isc(NA),
   c4(0),
   nc(2),
   ise(NA),
   c2(0),
   ne(1.5),
   ikf(NA),
   ikr(NA),
   irb(NA),
   rb(0),
   rbm(NA),
   re(0),
   rc(0),
   cbcp(0),
   cbep(0),
   cbsp(0),
   ccsp(0),
   cjc(0),
   cje(0),
   cjs(0),
   fc(NA),
   mjc(.33),
   mje(.33),
   mjs(0),
   vjc(.75),
   vje(.75),
   vjs(.75),
   xcjc(1),
   itf(0),
   ptf(0),
   tf(0),
   tr(0),
   vtf(NA),
   xtf(0),
   xtb(0),
   xti(3),
   eg(1.11),
   tnom_k(NA),
   polarity(pN),
   invearlyvoltf(NA),
   invearlyvoltr(NA),
   invrollofff(NA),
   invrolloffr(NA),
   transtimevbcfact(NA),
   excessphasefactor(NA),
   xfc(NA),
   f2(NA),
   f3(NA),
   f6(NA),
   f7(NA)
{
  ++_count;
  kf = 0;
  af = 1;
}
/*--------------------------------------------------------------------------*/
bool MODEL_BJT::parse_front(CS& cmd)
{
  return ONE_OF
    || set(cmd, "NPN", &polarity, pN)
    || set(cmd, "PNP", &polarity, pP)
    ;
}
/*--------------------------------------------------------------------------*/
bool MODEL_BJT::parse_params(CS& cmd)
{
  return ONE_OF
    || get(cmd, "KF", &kf)
    || get(cmd, "AF", &af)
    || get(cmd, "LEVEL", &level)
    || get(cmd, "BF", &bf)
    || get(cmd, "BFM", &bf)
    || get(cmd, "BR", &br)
    || get(cmd, "BRM", &br)
    || get(cmd, "IBC", &ibc)
    || get(cmd, "IBE", &ibe)
    || get(cmd, "IS", &is)
    || get(cmd, "NF", &nf)
    || get(cmd, "NR", &nr)
    || get(cmd, "VAf", &vaf)
    || get(cmd, "VBF", &vaf)
    || get(cmd, "VAR", &var)
    || get(cmd, "VB", &var)
    || get(cmd, "ISC", &isc)
    || get(cmd, "C4", &c4)
    || get(cmd, "JLC", &c4)
    || get(cmd, "NC", &nc)
    || get(cmd, "ISE", &ise)
    || get(cmd, "C2", &c2)
    || get(cmd, "JLE", &c2)
    || get(cmd, "NE", &ne)
    || get(cmd, "IKf", &ikf)
    || get(cmd, "JBF", &ikf)
    || get(cmd, "IKR", &ikr)
    || get(cmd, "JBR", &ikr)
    || get(cmd, "IRB", &irb)
    || get(cmd, "JRB", &irb)
    || get(cmd, "RB", &rb)
    || get(cmd, "RBM", &rbm)
    || get(cmd, "RE", &re)
    || get(cmd, "RC", &rc)
    || get(cmd, "CBCP", &cbcp)
    || get(cmd, "CBEP", &cbep)
    || get(cmd, "CBSP", &cbsp)
    || get(cmd, "CCSP", &ccsp)
    || get(cmd, "CJC", &cjc)
    || get(cmd, "CJE", &cje)
    || get(cmd, "CJS", &cjs)
    || get(cmd, "CCS", &cjs)
    || get(cmd, "FC", &fc)
    || get(cmd, "MJc", &mjc)
    || get(cmd, "MC", &mjc)
    || get(cmd, "MJE", &mje)
    || get(cmd, "ME", &mje)
    || get(cmd, "MJS", &mjs)
    || get(cmd, "MSub", &mjs)
    || get(cmd, "VJC", &vjc)
    || get(cmd, "PC", &vjc)
    || get(cmd, "VJE", &vje)
    || get(cmd, "PE", &vje)
    || get(cmd, "VJS", &vjs)
    || get(cmd, "PSub", &vjs)
    || get(cmd, "XCJC", &xcjc)
    || get(cmd, "CDIS", &xcjc)
    || get(cmd, "ITF", &itf)
    || get(cmd, "JTF", &itf)
    || get(cmd, "PTf", &ptf)
    || get(cmd, "TF", &tf)
    || get(cmd, "TR", &tr)
    || get(cmd, "VTF", &vtf)
    || get(cmd, "XTF", &xtf)
    || get(cmd, "XTB", &xtb)
    || get(cmd, "TB", &xtb)
    || get(cmd, "XTI", &xti)
    || get(cmd, "EG", &eg)
    ;
}
/*--------------------------------------------------------------------------*/
void MODEL_BJT::elabo1()
{
  if (1 || !evaluated()) {
    const CARD_LIST* par_scope = scope();
    assert(par_scope);
    // final adjust: code_pre
    // final adjust: override
    // final adjust: raw
    this->level.e_val(1, par_scope);
    this->bf.e_val(100, par_scope);
    this->br.e_val(1, par_scope);
    this->ibc.e_val(((is!=NA) ? is : 1e-16), par_scope);
    this->ibe.e_val(((is!=NA) ? is : 1e-16), par_scope);
    this->is.e_val(((ibe == ibc) ? ibe : NA), par_scope);
    this->nf.e_val(1, par_scope);
    this->nr.e_val(1, par_scope);
    this->vaf.e_val(NA, par_scope);
    this->var.e_val(NA, par_scope);
    this->isc.e_val((c4*is), par_scope);
    this->c4.e_val(0, par_scope);
    this->nc.e_val(2, par_scope);
    this->ise.e_val((c2*is), par_scope);
    this->c2.e_val(0, par_scope);
    this->ne.e_val(1.5, par_scope);
    this->ikf.e_val(NA, par_scope);
    this->ikr.e_val(NA, par_scope);
    this->irb.e_val(NA, par_scope);
    this->rb.e_val(0, par_scope);
    this->rbm.e_val(rb, par_scope);
    this->re.e_val(0, par_scope);
    this->rc.e_val(0, par_scope);
    this->cbcp.e_val(0, par_scope);
    this->cbep.e_val(0, par_scope);
    this->cbsp.e_val(0, par_scope);
    this->ccsp.e_val(0, par_scope);
    this->cjc.e_val(0, par_scope);
    this->cje.e_val(0, par_scope);
    this->cjs.e_val(0, par_scope);
    this->fc.e_val(.5, par_scope);
    //this->fc = std::min(fc, .9999);
    this->mjc.e_val(.33, par_scope);
    this->mje.e_val(.33, par_scope);
    this->mjs.e_val(0, par_scope);
    this->vjc.e_val(.75, par_scope);
    this->vje.e_val(.75, par_scope);
    this->vjs.e_val(.75, par_scope);
    this->xcjc.e_val(1, par_scope);
    this->itf.e_val(0, par_scope);
    this->ptf.e_val(0, par_scope);
    this->tf.e_val(0, par_scope);
    this->tr.e_val(0, par_scope);
    this->vtf.e_val(NA, par_scope);
    this->xtf.e_val(0, par_scope);
    this->xtb.e_val(0, par_scope);
    this->xti.e_val(3, par_scope);
    this->eg.e_val(1.11, par_scope);
    // final adjust: mid
    // final adjust: calculated
    tnom_k = _tnom_c + P_CELSIUS0;
    invearlyvoltf = (vaf != NA && vaf != 0.) ? 1./vaf : 0.;
    invearlyvoltr = (var != NA && var != 0.) ? 1./var : 0.;
    invrollofff = (ikf != NA && ikf != 0.) ? 1./ikf : 0.;
    invrolloffr = (ikr != NA && ikr != 0.) ? 1./ikr : 0.;
    transtimevbcfact = (vtf != NA && vtf != 0.) ? 1./(vtf*1.44) : 0.;
    excessphasefactor = (ptf * DTOR) * tf;
    xfc = log(1 - fc);
    f2 = exp((1 + mje) * xfc);
    f3 = 1 - fc * (1 + mje);
    f6 = exp((1 + mjc) * xfc);
    f7 = 1 - fc * (1 + mjc);
    // final adjust: post
    // final adjust: done
  }else{
    untested();
  }
}
/*--------------------------------------------------------------------------*/
SDP_CARD* MODEL_BJT::new_sdp(const COMMON_COMPONENT* c)const
{
  assert(c);
  {if (dynamic_cast<const COMMON_BJT*>(c)) {
    return new SDP_BJT(c);
  }else{
    return MODEL_DIODE::new_sdp(c);
  }}
}
/*--------------------------------------------------------------------------*/
void MODEL_BJT::print_front(OMSTREAM& o)const
{
  {if (polarity == pN) {
    o << "  npn";
  }else if (polarity == pP) {
    o << "  pnp";
  }else{
    unreachable();
  }}
}
/*--------------------------------------------------------------------------*/
void MODEL_BJT::print_params(OMSTREAM& o)const
{
  o << "level=1";
  o << "  kf=" << kf;
  o << "  af=" << af;
  if (false)
    o << "  level=" << level;
  o << "  bf=" << bf;
  o << "  br=" << br;
  if (ibe != ibc)
    o << "  ibc=" << ibc;
  if (ibe != ibc)
    o << "  ibe=" << ibe;
  if (ibe == ibc)
    o << "  is=" << is;
  o << "  nf=" << nf;
  o << "  nr=" << nr;
  if (vaf != NA)
    o << "  vaf=" << vaf;
  if (var != NA)
    o << "  var=" << var;
  if (isc != NA)
    o << "  isc=" << isc;
  o << "  c4=" << c4;
  o << "  nc=" << nc;
  if (ise != NA)
    o << "  ise=" << ise;
  o << "  c2=" << c2;
  o << "  ne=" << ne;
  if (ikf != NA)
    o << "  ikf=" << ikf;
  if (ikr != NA)
    o << "  ikr=" << ikr;
  if (irb != NA)
    o << "  irb=" << irb;
  o << "  rb=" << rb;
  if (rbm != NA)
    o << "  rbm=" << rbm;
  o << "  re=" << re;
  o << "  rc=" << rc;
  if (cbcp!=0)
    o << "  cbcp=" << cbcp;
  if (cbep!=0)
    o << "  cbep=" << cbep;
  if (cbsp!=0)
    o << "  cbsp=" << cbsp;
  if (ccsp!=0)
    o << "  ccsp=" << ccsp;
  o << "  cjc=" << cjc;
  o << "  cje=" << cje;
  o << "  cjs=" << cjs;
  if (fc != NA)
    o << "  fc=" << fc;
  o << "  mjc=" << mjc;
  o << "  mje=" << mje;
  o << "  mjs=" << mjs;
  o << "  vjc=" << vjc;
  o << "  vje=" << vje;
  o << "  vjs=" << vjs;
  o << "  xcjc=" << xcjc;
  o << "  itf=" << itf;
  o << "  ptf=" << ptf;
  o << "  tf=" << tf;
  o << "  tr=" << tr;
  if (vtf != NA)
    o << "  vtf=" << vtf;
  o << "  xtf=" << xtf;
  o << "  xtb=" << xtb;
  o << "  xti=" << xti;
  o << "  eg=" << eg;
}
/*--------------------------------------------------------------------------*/
void MODEL_BJT::print_calculated(OMSTREAM& o)const
{
  o << "";
}
/*--------------------------------------------------------------------------*/
bool MODEL_BJT::is_valid(const COMMON_COMPONENT* cc)const
{
  return MODEL_DIODE::is_valid(cc);
}
/*--------------------------------------------------------------------------*/
void MODEL_BJT::tr_eval(COMPONENT* brh)const
{
  DEV_BJT* d = prechecked_cast<DEV_BJT*>(brh);
  assert(d);
  const COMMON_BJT* c = prechecked_cast<const COMMON_BJT*>(d->common());
  assert(c);
  const SDP_BJT* s = prechecked_cast<const SDP_BJT*>(c->sdp());
  assert(s);
  const MODEL_BJT* m = this;
  const TDP_BJT T(d);
  const TDP_BJT* t = &T;

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    trace0("--------------------------");
    trace1(d->long_label().c_str(), d->evaliter());
    trace4("", d->vbe, d->vbc, d->vbx, d->vcs);
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    double cbe, gbe;
    { // d->cpi, d->gpi, d->cpixxx
      // uses: d->vbe
      double cben, gben;
      double vtn = t->vt * m->nf;
      double csat = t->ibe * c->area;
      double c2 = t->BEleakCur * c->area;
      {if (d->vbe > -5 * vtn) {
	double evbe = exp(d->vbe / vtn);
	cbe = csat * (evbe-1) + OPT::gmin * d->vbe;
	gbe = csat * evbe/vtn + OPT::gmin;
	{if (c2 == 0) {
	  cben = 0;
	  gben = 0;
	}else{
	  double vte = m->ne * t->vt;
	  double evben = exp(d->vbe / vte);
	  cben = c2 * (evben-1);
	  gben = c2 * evben/vte;
	}}
	trace4("vbe on", cbe, gbe, cben, gben);
      }else{
	gbe = -csat/d->vbe + OPT::gmin;
	cbe = gbe * d->vbe;
	gben = -c2 / d->vbe;
	cben = gben * d->vbe;
	trace4("vbe off", cbe, gbe, cben, gben);
      }}
      d->cpi = cbe / t->BetaF + cben;
      d->gpi = gbe / t->BetaF + gben;
      d->cpixxx = d->cpi - d->vbe * d->gpi;
      trace3("", t->BetaF, d->cpi, d->gpi);
    }
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    double cbc, gbc, cbcn;
    { // d->cmu, d->gmu, d->cmuxxx
      // uses: d->vbc
      double gbcn;
      double vtn = t->vt * m->nr;
      double csat = t->ibc * c->area;
      double c4 = t->BCleakCur * c->area;
      {if (d->vbc > -5 * vtn) {
	double evbc = exp(d->vbc / vtn);
	cbc = csat * (evbc-1) + OPT::gmin * d->vbc;
	gbc = csat * evbc/vtn + OPT::gmin;
	{if (c4 == 0) {
	  cbcn = 0;
	  gbcn = 0;
	}else{
	  double vtc = m->nc * t->vt;
	  double evbcn = exp(d->vbc / vtc);
	  cbcn = c4 * (evbcn-1);
	  gbcn = c4 * evbcn/vtc;
	}}
	trace4("vbc on", cbc, gbc, cbcn, gbcn);
      }else{
	gbc = -csat/d->vbc + OPT::gmin;
	cbc = gbc * d->vbc;
	gbcn = -c4 / d->vbc;
	cbcn = gbcn * d->vbc;
	trace4("vbc off", cbc, gbc, cbcn, gbcn);
      }}
      d->cmu = cbc / t->BetaR + cbcn;
      d->gmu = gbc / t->BetaR + gbcn;
      d->cmuxxx = d->cmu - d->vbc * d->gmu;
      trace3("", t->BetaR, d->cmu, d->gmu);
    }
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //   determine base charge terms
    double qb, dqbdve, dqbdvc;
    {
      double q1 = 1 / (1 - m->invearlyvoltf*d->vbc - m->invearlyvoltr*d->vbe);
      {if(c->oik == 0 && c->oikr == 0) {
	qb = q1;
	dqbdve = q1 * qb * m->invearlyvoltr;
	dqbdvc = q1 * qb * m->invearlyvoltf;
	trace4("!oik", q1, qb, dqbdve, dqbdvc);
      }else{
	double q2 = c->oik * cbe + c->oikr * cbc;
	double arg = std::max(0., 1+4*q2);
	double sqarg = (arg == 0) ? 1 : sqrt(arg);
	qb = q1 * (1+sqarg) / 2;
	dqbdve = q1 * (qb * m->invearlyvoltr + c->oik  * gbe / sqarg);
	dqbdvc = q1 * (qb * m->invearlyvoltf + c->oikr * gbc / sqarg);
	trace2("", c->oik, c->oikr);
	trace4("oik", q1, qb, dqbdve, dqbdvc);
      }}
    }
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // weil's approx. for excess phase applied with backward-euler integration
    {
      double cc = 0;
      double cex = cbe;
      double gex = gbe;
      if (0 && m->excessphasefactor != 0) {
	unreachable();
	incomplete(); // doesn't save old values of cexbc, so disabled
	double arg1 = d->_dt_0 / m->excessphasefactor;
	double arg2 = 3 * arg1;
	arg1 *= arg2;
	double denom = 1 + arg1 + arg2;
	double arg3 = arg1 / denom;
	if (initial_step(SIM::mode)) {
	  d->cexbc_2 = d->cexbc_1 = cbe / qb;
	}
	cc = (d->cexbc_1 * (1 + d->_dt_0/d->_dt_1 + arg2)
	      - d->cexbc_2 * d->_dt_0/d->_dt_1) / denom;
	cex *= arg3;
	gex *= arg3;
      }
      d->cexbc_0 = cc + cex / qb;

      d->cce = cc + (cex-cbc)/qb - cbc/t->BetaR - cbcn;
      d->go = (gbc + (cex-cbc)*dqbdvc / qb) / qb;
      d->gm = (gex - (cex-cbc)*dqbdve / qb) / qb - d->go;
      d->ccexxx = d->cce - ((d->vbe - d->vbc) * d->go + d->vbe * d->gm);
      trace4("", d->cce, d->go, d->gm, d->cce/t->vt);
    }
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // d->gx
    // should be moved to a private eval
    // may use d->cpi, d->cmu, qb
    {
      {if (!OPT::rstray || (m->rb == 0. && m->rbm == 0.)) {
	trace3("", m->rb, m->irb, d->gx);
	assert(d->gx == NA);
      }else{
	double rx = NA;
	double rbpr = m->rbm / c->area;
	double rbpi = m->rb / c->area - rbpr;
	{if (m->irb != 0) { // base resistance lowering at high current
	  double cb = d->cpi + d->cmu;
	  double xjrb = m->irb * c->area;
	  double arg1 = std::max(cb/xjrb, 1e-9);
	  double arg2 = (-1 + sqrt(1+14.59025*arg1)) / 2.4317 / sqrt(arg1);
	  arg1 = tan(arg2);
	  rx = rbpr + 3 * rbpi * (arg1-arg2) / arg2 / arg1 / arg1;
	}else{
	  rx = rbpr + rbpi / qb;
	}}
	trace3("", m->rb, m->irb, rx);
	assert(rx != NA);
	assert(rx != 0);
	d->gx = 1 / rx;
	trace1("", d->gx);
      }}
    }
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    const bool charge_computation_needed = OPT::cstray;
    if (charge_computation_needed) {
      {if (m->tf != 0 && d->vbe > 0) {
	double argtf = NA;
	double arg2  = NA;
	double arg3  = NA;
	{if (m->xtf != 0) {
	  {if (m->transtimevbcfact != 0) {
	    //untested();
	    argtf = m->xtf * exp(d->vbc * m->transtimevbcfact);
	  }else{
	    untested();
	    argtf = m->xtf;
	  }}
	  arg2 = argtf;
	  {if(m->itf != 0) {
	    //untested();
	    double temp = cbe / (cbe + m->itf * c->area);
	    argtf *= temp*temp;
	    arg2  *= (3-temp-temp);
	  }else{
	    //untested();
	  }}
	  arg3 = cbe * argtf * m->transtimevbcfact;
	}else{
	  arg3 = arg2 = argtf = 0;
	}}
	assert(argtf != NA);
	assert(arg2  != NA);
	assert(arg3  != NA);
	cbe *= (1+argtf) / qb;
	gbe = (gbe * (1+arg2) - cbe * dqbdve) / qb;
	d->geqcb=m->tf*(arg3-cbe*dqbdvc)/qb;
      }else{
	d->geqcb=0;
      }}
      { // d->qbe, d->cqbe
	// uses: d->vbe, cbe, gbe
	double czbe = t->BEcap * c->area;
	{if (d->vbe < t->DepCap) {
	  double arg = 1 - d->vbe / t->BEpot;
	  double sarg = pow(arg, -m->mje);
	  d->qbe = m->tf * cbe + t->BEpot * czbe * (1-arg*sarg) / (1 - m->mje);
	  d->cqbe = m->tf * gbe + czbe * sarg;
	}else{
	  double czbef2 = czbe / m->f2;
	  d->qbe = m->tf * cbe + czbe * t->f1 
	    + czbef2 * (m->f3 * (d->vbe - t->DepCap)
			+ (m->mje / (2. * t->BEpot))
			* (d->vbe * d->vbe - t->DepCap * t->DepCap));
	  d->cqbe = m->tf * gbe + czbef2 * (m->f3 + m->mje*d->vbe / t->BEpot);
	}}
      }
      { // d->qbc, d->cqbc
	// uses: d->vbc, cbc, gbc
	double czbc = t->BCcap * c->area * m->xcjc;
	{if (d->vbc < t->f4) {
	  double arg = 1 - d->vbc / t->BCpot;
	  double sarg = pow(arg, -m->mjc);
	  d->qbc = m->tr *cbc + t->BCpot *czbc * (1 - arg*sarg) / (1 - m->mjc);
	  d->cqbc = m->tr * gbc + czbc * sarg;
	}else{
	  double czbcf2 = czbc / m->f6;
	  d->qbc = m->tr * cbc + czbc * t->f5
	    + czbcf2 * (m->f7 * (d->vbc-t->f4) 
		+ (m->mjc/(t->BCpot+t->BCpot)) * (d->vbc*d->vbc-t->f4*t->f4));
	  d->cqbc = m->tr * gbc + czbcf2 * (m->f7 + m->mjc * d->vbc/t->BCpot);
	}}
      }
      { // d->qbx, d->cqbx
	// uses: d->vbx
	double czbx = t->BCcap * c->area * (1 - m->xcjc);
	{if (d->vbx < t->f4) {
	  double arg = 1 - d->vbx / t->BCpot;
	  double sarg = pow(arg, -m->mjc);
	  d->qbx = t->BCpot * czbx * (1 - arg*sarg) / (1 - m->mjc);
	  d->cqbx = czbx * sarg;
	}else{
	  double czbxf2 = czbx / m->f6;
	  d->qbx = czbx * t->f5 + czbxf2 
	    * (m->f7 * (d->vbx-t->f4)
	      + (m->mjc / (t->BCpot+t->BCpot)) * (d->vbx*d->vbx-t->f4*t->f4));
	  d->cqbx = czbxf2 * (m->f7 + m->mjc * d->vbx / t->BCpot);
	}}
      }
      { // d->qcs, d->cqcs
	// uses: d->vcs
	double czcs = m->cjs * c->area;
	{if (d->vcs < 0) {
	  double arg = 1 - d->vcs / m->vjs;
	  double sarg = pow(arg, -m->mjs);
	  d->qcs = m->vjs * czcs * (1 - arg*sarg) / (1 - m->mjs);
	  d->cqcs = czcs * sarg;
	}else{
	  d->qcs = d->vcs * czcs * (1 + m->mjs * d->vcs / (2 * m->vjs));
	  d->cqcs = czcs * (1 + m->mjs * d->vcs / m->vjs);
	}}
      }
    }
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
int DEV_BJT::_count = 0;
int COMMON_BJT::_count = -1;
static COMMON_BJT Default_BJT(CC_STATIC);
/*--------------------------------------------------------------------------*/
COMMON_BJT::COMMON_BJT(int c)
  :COMMON_COMPONENT(c),
   m(1.0),
   area(1),
   off(false),
   icvbe(NA),
   icvce(NA),
   temp(NA),
   _sdp(0),
   oik(NA),
   oikr(NA)
{
  ++_count;
}
/*--------------------------------------------------------------------------*/
COMMON_BJT::COMMON_BJT(const COMMON_BJT& p)
  :COMMON_COMPONENT(p),
   m(p.m),
   area(p.area),
   off(p.off),
   icvbe(p.icvbe),
   icvce(p.icvce),
   temp(p.temp),
   _sdp(0),
   oik(p.oik),
   oikr(p.oikr)
{
  ++_count;
}
/*--------------------------------------------------------------------------*/
COMMON_BJT::~COMMON_BJT()
{
  --_count;
  delete _sdp;
}
/*--------------------------------------------------------------------------*/
bool COMMON_BJT::operator==(const COMMON_COMPONENT& x)const
{
  const COMMON_BJT* p = dynamic_cast<const COMMON_BJT*>(&x);
  return (p
    && m == p->m
    && area == p->area
    && off == p->off
    && icvbe == p->icvbe
    && icvce == p->icvce
    && temp == p->temp
    && _sdp == p->_sdp
    && COMMON_COMPONENT::operator==(x));
}
/*--------------------------------------------------------------------------*/
void COMMON_BJT::parse(CS& cmd)
{
  parse_modelname(cmd);
  if (cmd.is_float()) {
    cmd >> area;
  }
  int here = cmd.cursor();
  do{
    ONE_OF
    || get(cmd, "M", &m)
    || get(cmd, "Area", &area)
    || get(cmd, "OFF", &off)
    || get(cmd, "ICVBE", &icvbe)
    || get(cmd, "ICVCE", &icvce)
    || get(cmd, "TEMP", &temp)
    ;
  }while (cmd.more() && !cmd.stuck(&here));
  cmd.check(bWARNING, "what's this?");
}
/*--------------------------------------------------------------------------*/
void COMMON_BJT::print(OMSTREAM& o)const
{
  o << "  " << modelname();
  o.setfloatwidth(7);
  if (m != 1.)
    o << "  m=" << m;
  o << "  area=" << area;
  if (off)
    o << "  off=" << off;
  if (icvbe != NA)
    o << "  icvbe=" << icvbe;
  if (icvce != NA)
    o << "  icvce=" << icvce;
  if (temp != NA)
    o << "  temp=" << temp;
  o << '\n';
}
/*--------------------------------------------------------------------------*/
void COMMON_BJT::elabo3(const COMPONENT* d)
{
  COMMON_BJT* c = this;
  const MODEL_BJT* m = dynamic_cast<const MODEL_BJT*>(attach_model(d));
  if (!m) {
    error(bERROR, d->long_label() + ": model " + modelname()
          + " is not a bjt\n");
  }

  assert(c);
  const CARD_LIST* par_scope = d->scope();
  assert(par_scope);
    // final adjust: code_pre
    // final adjust: override
    // final adjust: raw
    this->m.e_val(1.0, par_scope);
    this->area.e_val(1, par_scope);
    this->off.e_val(false, par_scope);
    this->icvbe.e_val(NA, par_scope);
    this->icvce.e_val(NA, par_scope);
    this->temp.e_val(NA, par_scope);
    // final adjust: mid
    // final adjust: calculated
    oik = m->invrollofff / c->area;
    oikr = m->invrolloffr / c->area;
    // final adjust: post
    // final adjust: done

  // size dependent
  delete _sdp;
  _sdp = m->new_sdp(this);
  assert(_sdp);
  const SDP_BJT* s = dynamic_cast<const SDP_BJT*>(_sdp);
  assert(s);

  // subcircuit commons, recursive
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
DEV_BJT::DEV_BJT()
  :BASE_SUBCKT(),
   // input parameters,
   // calculated parameters,
   vbe(NA),
   vbc(NA),
   vbx(NA),
   vcs(NA),
   cce(NA),
   ccexxx(NA),
   go(NA),
   gm(NA),
   cpi(NA),
   cpixxx(NA),
   gpi(NA),
   cmu(NA),
   cmuxxx(NA),
   gmu(NA),
   ixxxx(0),
   gx(NA),
   qbx(NA),
   cqbx(NA),
   qbc(NA),
   cqbc(NA),
   qcs(NA),
   cqcs(NA),
   qbe(NA),
   cqbe(NA),
   geqcb(NA),
   cexbc_0(NA),
   cexbc_1(NA),
   cexbc_2(NA),
   _dt_0(NA),
   _dt_1(NA),
   // netlist,
   _Ice(0),
   _Ipi(0),
   _Imu(0),
   _Cbx(0),
   _Cbc(0),
   _Ccs(0),
   _Cbe(0),
   _Rc(0),
   _Re(0),
   _Yb(0),
   _Cbcp(0),
   _Cbep(0),
   _Cbs(0)
{
  _n = _nodes + int_nodes();
  attach_common(&Default_BJT);
  ++_count;
  // overrides
}
/*--------------------------------------------------------------------------*/
DEV_BJT::DEV_BJT(const DEV_BJT& p)
  :BASE_SUBCKT(p),
   // input parameters,
   // calculated parameters,
   vbe(p.vbe),
   vbc(p.vbc),
   vbx(p.vbx),
   vcs(p.vcs),
   cce(p.cce),
   ccexxx(p.ccexxx),
   go(p.go),
   gm(p.gm),
   cpi(p.cpi),
   cpixxx(p.cpixxx),
   gpi(p.gpi),
   cmu(p.cmu),
   cmuxxx(p.cmuxxx),
   gmu(p.gmu),
   ixxxx(p.ixxxx),
   gx(p.gx),
   qbx(p.qbx),
   cqbx(p.cqbx),
   qbc(p.qbc),
   cqbc(p.cqbc),
   qcs(p.qcs),
   cqcs(p.cqcs),
   qbe(p.qbe),
   cqbe(p.cqbe),
   geqcb(p.geqcb),
   cexbc_0(p.cexbc_0),
   cexbc_1(p.cexbc_1),
   cexbc_2(p.cexbc_2),
   _dt_0(p._dt_0),
   _dt_1(p._dt_1),
   // netlist,
   _Ice(0),
   _Ipi(0),
   _Imu(0),
   _Cbx(0),
   _Cbc(0),
   _Ccs(0),
   _Cbe(0),
   _Rc(0),
   _Re(0),
   _Yb(0),
   _Cbcp(0),
   _Cbep(0),
   _Cbs(0)
{
  _n = _nodes + int_nodes();
  for (int ii = -int_nodes(); ii < max_nodes(); ++ii) {
    _n[ii] = p._n[ii];
  }
  ++_count;
  // overrides
}
/*--------------------------------------------------------------------------*/
void DEV_BJT::elabo1()
{
  BASE_SUBCKT::elabo1();
  const COMMON_BJT* c = prechecked_cast<const COMMON_BJT*>(common());
  assert(c);
  const MODEL_BJT* m = prechecked_cast<const MODEL_BJT*>(c->model());
  assert(m);
  const SDP_BJT* s = prechecked_cast<const SDP_BJT*>(c->sdp());
  assert(s);
  if (!subckt()) {
    new_subckt();
  }

  // local nodes
  {if (!OPT::rstray || m->rc == 0.) {
    _n[n_icol] = _n[n_col];
  }else{
    _n[n_icol].new_model_node();
  }}
  {if (!OPT::rstray || (m->rb == 0. && m->rbm == 0.)) {
    _n[n_ibase] = _n[n_base];
  }else{
    _n[n_ibase].new_model_node();
  }}
  {if (!OPT::rstray || m->re == 0.) {
    _n[n_iemit] = _n[n_emit];
  }else{
    _n[n_iemit].new_model_node();
  }}

  // clone subckt elements
  {{
    if (!_Ice) {
      _Ice = new DEV_CPOLY_G;
      subckt()->push_front(_Ice);
    }
    {{
      node_t nodes[] = {_n[n_icol], _n[n_iemit], _n[n_ibase], _n[n_iemit]};
      _Ice->set_parameters("Ice", this, NULL, 0., 3, &ccexxx, 4, nodes);
    }}
  }}
  {{
    if (!_Ipi) {
      _Ipi = new DEV_CPOLY_G;
      subckt()->push_front(_Ipi);
    }
    {{
      node_t nodes[] = {_n[n_ibase], _n[n_iemit]};
      _Ipi->set_parameters("Ipi", this, NULL, 0., 2, &cpixxx, 2, nodes);
    }}
  }}
  {{
    if (!_Imu) {
      _Imu = new DEV_CPOLY_G;
      subckt()->push_front(_Imu);
    }
    {{
      node_t nodes[] = {_n[n_ibase], _n[n_icol]};
      _Imu->set_parameters("Imu", this, NULL, 0., 2, &cmuxxx, 2, nodes);
    }}
  }}
  {{
    if (!_Cbx) {
      _Cbx = new DEV_FPOLY_CAP;
      subckt()->push_front(_Cbx);
    }
    {{
      node_t nodes[] = {_n[n_base], _n[n_icol]};
      _Cbx->set_parameters("Cbx", this, NULL, 0., 2, &qbx, 2, nodes);
    }}
  }}
  {{
    if (!_Cbc) {
      _Cbc = new DEV_FPOLY_CAP;
      subckt()->push_front(_Cbc);
    }
    {{
      node_t nodes[] = {_n[n_ibase], _n[n_icol]};
      _Cbc->set_parameters("Cbc", this, NULL, 0., 2, &qbc, 2, nodes);
    }}
  }}
  {if (!(_n[n_sub].n_())) {
    if (_Ccs) {
      subckt()->erase(_Ccs);
      _Ccs = NULL;
    }
  }else{
    if (!_Ccs) {
      _Ccs = new DEV_FPOLY_CAP;
      subckt()->push_front(_Ccs);
    }
    {{
      node_t nodes[] = {_n[n_sub], _n[n_icol]};
      _Ccs->set_parameters("Ccs", this, NULL, 0., 2, &qcs, 2, nodes);
    }}
  }}
  {{
    if (!_Cbe) {
      _Cbe = new DEV_FPOLY_CAP;
      subckt()->push_front(_Cbe);
    }
    {{
      node_t nodes[] = {_n[n_ibase], _n[n_iemit], _n[n_ibase], _n[n_icol]};
      _Cbe->set_parameters("Cbe", this, NULL, 0., 3, &qbe, 4, nodes);
    }}
  }}
  {if (!OPT::rstray || m->rc == 0.) {
    if (_Rc) {
      subckt()->erase(_Rc);
      _Rc = NULL;
    }
  }else{
    if (!_Rc) {
      _Rc = new DEV_RESISTANCE;
      subckt()->push_front(_Rc);
    }
    {{
      node_t nodes[] = {_n[n_col], _n[n_icol]};
      _Rc->set_parameters("Rc", this, NULL, m->rc / (c->area * c->m), 0, 0, 2, nodes);
    }}
  }}
  {if (!OPT::rstray || m->re == 0.) {
    if (_Re) {
      subckt()->erase(_Re);
      _Re = NULL;
    }
  }else{
    if (!_Re) {
      _Re = new DEV_RESISTANCE;
      subckt()->push_front(_Re);
    }
    {{
      node_t nodes[] = {_n[n_emit], _n[n_iemit]};
      _Re->set_parameters("Re", this, NULL, m->re / (c->area * c->m), 0, 0, 2, nodes);
    }}
  }}
  {if (!OPT::rstray || (m->rb == 0. && m->rbm == 0.)) {
    if (_Yb) {
      subckt()->erase(_Yb);
      _Yb = NULL;
    }
  }else{
    if (!_Yb) {
      _Yb = new DEV_CPOLY_G;
      subckt()->push_front(_Yb);
    }
    {{
      node_t nodes[] = {_n[n_base], _n[n_ibase]};
      _Yb->set_parameters("Yb", this, NULL, 0., 2, &ixxxx, 2, nodes);
    }}
  }}
  {if (!OPT::cstray || m->cbcp == 0.) {
    if (_Cbcp) {
      subckt()->erase(_Cbcp);
      _Cbcp = NULL;
    }
  }else{
    if (!_Cbcp) {
      _Cbcp = new DEV_CAPACITANCE;
      subckt()->push_front(_Cbcp);
    }
    {{
      node_t nodes[] = {_n[n_base], _n[n_col]};
      _Cbcp->set_parameters("Cbcp", this, NULL, m->cbcp * c->area * c->m, 0, 0, 2, nodes);
    }}
  }}
  {if (!OPT::cstray || m->cbep == 0.) {
    if (_Cbep) {
      subckt()->erase(_Cbep);
      _Cbep = NULL;
    }
  }else{
    if (!_Cbep) {
      _Cbep = new DEV_CAPACITANCE;
      subckt()->push_front(_Cbep);
    }
    {{
      node_t nodes[] = {_n[n_base], _n[n_emit]};
      _Cbep->set_parameters("Cbep", this, NULL, m->cbep * c->area * c->m, 0, 0, 2, nodes);
    }}
  }}
  {if (!OPT::cstray || ((m->cbsp + m->ccsp) == 0.)) {
    if (_Cbs) {
      subckt()->erase(_Cbs);
      _Cbs = NULL;
    }
  }else{
    if (!_Cbs) {
      _Cbs = new DEV_CAPACITANCE;
      subckt()->push_front(_Cbs);
    }
    {{
      node_t nodes[] = {_n[n_base], _n[n_sub]};
      _Cbs->set_parameters("Cbs", this, NULL, (m->cbsp + m->ccsp) * c->area * c->m, 0, 0, 2, nodes);
    }}
  }}
  subckt()->elabo2();
  assert(!is_constant());
  subckt()->set_slave();
}
/*--------------------------------------------------------------------------*/
double DEV_BJT::tr_probe_num(CS& cmd)const
{
  const COMMON_BJT* c = prechecked_cast<const COMMON_BJT*>(common());
  assert(c);
  const MODEL_BJT* m = prechecked_cast<const MODEL_BJT*>(c->model());
  assert(m);
  const SDP_BJT* s = prechecked_cast<const SDP_BJT*>(c->sdp());
  assert(s);

  {if (cmd.pmatch("VBEInt")) {
    return  vbe;
  }else if (cmd.pmatch("VBCInt")) {
    return  vbc;
  }else if (cmd.pmatch("VBXInt")) {
    return  vbx;
  }else if (cmd.pmatch("VCSInt")) {
    return  vcs;
  }else if (cmd.pmatch("VBS")) {
    return  _n[n_base].v0() - _n[n_sub].v0();
  }else if (cmd.pmatch("VBE")) {
    return  _n[n_base].v0() - _n[n_emit].v0();
  }else if (cmd.pmatch("VBC")) {
    return  _n[n_base].v0() - _n[n_col].v0();
  }else if (cmd.pmatch("VBX")) {
    return  _n[n_base].v0() - _n[n_ibase].v0();
  }else if (cmd.pmatch("VCS")) {
    return  _n[n_col].v0() - _n[n_sub].v0();
  }else if (cmd.pmatch("VCB")) {
    return  _n[n_col].v0() - _n[n_base].v0();
  }else if (cmd.pmatch("VCE")) {
    return  _n[n_col].v0() - _n[n_emit].v0();
  }else if (cmd.pmatch("VES")) {
    return  _n[n_emit].v0() - _n[n_sub].v0();
  }else if (cmd.pmatch("VEB")) {
    return  _n[n_emit].v0() - _n[n_base].v0();
  }else if (cmd.pmatch("VEC")) {
    return  _n[n_emit].v0() - _n[n_col].v0();
  }else if (cmd.pmatch("VB")) {
    return  _n[n_base].v0();
  }else if (cmd.pmatch("VC")) {
    return  _n[n_col].v0();
  }else if (cmd.pmatch("VE")) {
    return  _n[n_emit].v0();
  }else if (cmd.pmatch("VS")) {
    return  _n[n_sub].v0();
  }else if (cmd.pmatch("VBI")) {
    return  _n[n_ibase].v0();
  }else if (cmd.pmatch("VCI")) {
    return  _n[n_icol].v0();
  }else if (cmd.pmatch("VEI")) {
    return  _n[n_iemit].v0();
  }else if (cmd.pmatch("ICE")) {
    return  cce;
  }else if (cmd.pmatch("ICEOffset")) {
    return  ccexxx;
  }else if (cmd.pmatch("HOE")) {
    return  go;
  }else if (cmd.pmatch("ROe")) {
    return  (go != 0) ? 1/go : BIGBIG;
  }else if (cmd.pmatch("IPI")) {
    return  cpi;
  }else if (cmd.pmatch("IPIOffset")) {
    return  cpixxx;
  }else if (cmd.pmatch("RPI")) {
    return  (gpi != 0) ? 1/gpi : BIGBIG;
  }else if (cmd.pmatch("HIE")) {
    return  (gpi != 0) ? 1/gpi : BIGBIG;
  }else if (cmd.pmatch("IMU")) {
    return  cmu;
  }else if (cmd.pmatch("IMUOffset")) {
    return  cmuxxx;
  }else if (cmd.pmatch("RMU")) {
    return  (gmu != 0) ? 1/gmu : BIGBIG;
  }else if (cmd.pmatch("IB")) {
    return  cpi + cmu;
  }else if (cmd.pmatch("RX")) {
    return  (gx != NA) ? 1/gx : 0.;
  }else if (cmd.pmatch("IC")) {
    return  cce - cmu;
  }else if (cmd.pmatch("IE")) {
    return  -cce -cpi;
  }else if (cmd.pmatch("CBX")) {
    return  cqbx;
  }else if (cmd.pmatch("CBC")) {
    return  cqbc;
  }else if (cmd.pmatch("CMU")) {
    return  cqbc;
  }else if (cmd.pmatch("CCS")) {
    return  cqcs;
  }else if (cmd.pmatch("CBE")) {
    return  cqbe;
  }else if (cmd.pmatch("CPI")) {
    return  cqbe;
  }else if (cmd.pmatch("P")) {
    return  CARD::probe(_Ice,"P") + CARD::probe(_Ipi,"P") + CARD::probe(_Imu,"P") + CARD::probe(_Rc,"P") + CARD::probe(_Re,"P") + CARD::probe(_Yb,"P") + CARD::probe(_Cbx,"P") + CARD::probe(_Cbc,"P") + CARD::probe(_Ccs,"P") + CARD::probe(_Cbe,"P");
  }else if (cmd.pmatch("PD")) {
    return  CARD::probe(_Ice,"PD") + CARD::probe(_Ipi,"PD") + CARD::probe(_Imu,"PD") + CARD::probe(_Rc,"PD") + CARD::probe(_Re,"PD") + CARD::probe(_Yb,"PD") + CARD::probe(_Cbx,"PD") + CARD::probe(_Cbc,"PD") + CARD::probe(_Ccs,"PD") + CARD::probe(_Cbe,"PD");
  }else if (cmd.pmatch("PS")) {
    return  CARD::probe(_Ice,"PS") + CARD::probe(_Ipi,"PS") + CARD::probe(_Imu,"PS") + CARD::probe(_Rc,"PS") + CARD::probe(_Re,"PS") + CARD::probe(_Yb,"PS") + CARD::probe(_Cbx,"PS") + CARD::probe(_Cbc,"PS") + CARD::probe(_Ccs,"PS") + CARD::probe(_Cbe,"PS");
  }else if (cmd.pmatch("Status")) {
    return  static_cast<double>(converged() * 2);
  }else if (cmd.pmatch("VBE")) {
    return vbe;
  }else if (cmd.pmatch("VBC")) {
    return vbc;
  }else if (cmd.pmatch("VBX")) {
    return vbx;
  }else if (cmd.pmatch("VCS")) {
    return vcs;
  }else if (cmd.pmatch("CCE")) {
    return cce;
  }else if (cmd.pmatch("CCEXXX")) {
    return ccexxx;
  }else if (cmd.pmatch("GO")) {
    return go;
  }else if (cmd.pmatch("GM")) {
    return gm;
  }else if (cmd.pmatch("CPI")) {
    return cpi;
  }else if (cmd.pmatch("CPIXXX")) {
    return cpixxx;
  }else if (cmd.pmatch("GPI")) {
    return gpi;
  }else if (cmd.pmatch("CMU")) {
    return cmu;
  }else if (cmd.pmatch("CMUXXX")) {
    return cmuxxx;
  }else if (cmd.pmatch("GMU")) {
    return gmu;
  }else if (cmd.pmatch("IXXXX")) {
    return ixxxx;
  }else if (cmd.pmatch("GX")) {
    return gx;
  }else if (cmd.pmatch("QBX")) {
    return qbx;
  }else if (cmd.pmatch("CQBX")) {
    return cqbx;
  }else if (cmd.pmatch("QBC")) {
    return qbc;
  }else if (cmd.pmatch("CQBC")) {
    return cqbc;
  }else if (cmd.pmatch("QCS")) {
    return qcs;
  }else if (cmd.pmatch("CQCS")) {
    return cqcs;
  }else if (cmd.pmatch("QBE")) {
    return qbe;
  }else if (cmd.pmatch("CQBE")) {
    return cqbe;
  }else if (cmd.pmatch("GEQCB")) {
    return geqcb;
  }else if (cmd.pmatch("CEXBC_0")) {
    return cexbc_0;
  }else if (cmd.pmatch("CEXBC_1")) {
    return cexbc_1;
  }else if (cmd.pmatch("CEXBC_2")) {
    return cexbc_2;
  }else if (cmd.pmatch("_DT_0")) {
    return _dt_0;
  }else if (cmd.pmatch("_DT_1")) {
    return _dt_1;
  }else {
    return BASE_SUBCKT::tr_probe_num(cmd);
  }}
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------*/
bool DEV_BJT::tr_needs_eval()
{
  {if (is_q_for_eval()) {
    untested();
    return false;
  }else if (!converged()) {
    return true;
  }else{
    const COMMON_BJT* c = prechecked_cast<const COMMON_BJT*>(common());
    assert(c);
    const MODEL_BJT* m=prechecked_cast<const MODEL_BJT*>(c->model());
    assert(m);
    polarity_t polarity = m->polarity;
    return !(conchk(vbc, polarity*(_n[n_ibase].v0()-_n[n_icol].v0()),
		    OPT::vntol)
	     && conchk(vbe, polarity*(_n[n_ibase].v0()-_n[n_iemit].v0()),
		       OPT::vntol)
	     && conchk(vcs, polarity*(_n[n_icol].v0()-_n[n_sub].v0()),
		       OPT::vntol));
  }}
}
/*--------------------------------------------------------------------------*/
bool DEV_BJT::do_tr()
{
  const COMMON_BJT* c = prechecked_cast<const COMMON_BJT*>(common());
  assert(c);
  const MODEL_BJT* m = prechecked_cast<const MODEL_BJT*>(c->model());
  assert(m);
  const TDP_BJT T(this);
  const TDP_BJT* t = &T;

  {if(initial_step(SIM::mode)) {	// initial guess
    {if (c->off) {
      vbe = 0;
    }else{
      double vt = (SIM::temp_c + P_CELSIUS0) * P_K_Q;
      vbe = vt * log(vt / (M_SQRT2 * m->ibe));
    }}
    vbc = 0;
    /* ERROR:  need to initialize VCS, VBX here */
    vcs = vbx = 0;
  }else{				// normal gather
    vbe = pnj_limit((m->polarity * volts_limited(_n[n_ibase], _n[n_iemit])),
		    vbe, t->vt, t->Vcrit);
    vbc = pnj_limit((m->polarity * volts_limited(_n[n_ibase], _n[n_icol])),
		    vbc, t->vt, t->Vcrit);
    vbx = m->polarity * volts_limited(_n[n_base], _n[n_icol]);
    vcs = m->polarity * volts_limited(_n[n_sub], _n[n_icol]);
  }}
 
  if (SIM::uic_now()) {
    untested();
    {if (c->icvbe != NA) {
      untested();
      vbe = m->polarity * c->icvbe;
    }else{
      untested();
    }}
    {if (c->icvce != NA) {
      untested();
      vbc = vbe - m->polarity * c->icvce;
      vbx = vbc;
    }else{
      untested();
    }}
  }

  m->tr_eval(this);
  switch (m->polarity) {
  case pP:
    cce = -cce;
    ccexxx = -ccexxx;
    cpi = -cpi;
    cpixxx = -cpixxx;
    cmu = -cmu;
    cmuxxx = -cmuxxx;
    assert(ixxxx == 0.);
    qbx = -qbx;
    qbc = -qbc;
    qcs = -qcs;
    qbe = -qbe;
    break;
  case pN:
    // leave it as is
    break;
  }
  if (c->m != 1.) {
    cce *= c->m;
    ccexxx *= c->m;
    go *= c->m;
    gm *= c->m;
    
    cpi *= c->m;
    cpixxx *= c->m;
    gpi *= c->m;
    
    cmu *= c->m;
    cmuxxx *= c->m;
    gmu *= c->m;
    
    ixxxx *= c->m;
    gx  *= c->m;
    
    qbx *= c->m;
    cqbx *= c->m;
    
    qbc  *= c->m;
    cqbc *= c->m;
    
    qcs  *= c->m;
    cqcs *= c->m;
    
    qbe  *= c->m;
    cqbe *= c->m;
    geqcb *= c->m;
  }
  
  assert(subckt());
  set_converged(subckt()->do_tr());
  return converged();
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
