/* $Id: d_mos5.model,v 26.92 2008/08/23 05:40:00 al Exp $ -*- C++ -*-
 * Copyright (C) 2001 Albert Davis
 * Author: Albert Davis <aldavis@gnu.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 3, 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.
 *------------------------------------------------------------------
 * Spice BSIM2 model
 * derived from Spice3f4,Copyright 1990 Regents of the University of California
 * 1988 Min-Chie Jeng, Hong J. Park, Thomas L. Quarles
 * Recoded for Gnucap model compiler, Al Davis, 2000
 */
/* This file is automatically generated. DO NOT EDIT */

#include "globals.h"
#include "e_elemnt.h"
#include "d_mos5.h"
/*--------------------------------------------------------------------------*/
const double NA(NOT_INPUT);
const double INF(BIGBIG);
/*--------------------------------------------------------------------------*/
int MODEL_BUILT_IN_MOS5::_count = 0;
/*--------------------------------------------------------------------------*/
const int LEVEL(5);
/*--------------------------------------------------------------------------*/
namespace MODEL_BUILT_IN_MOS5_DISPATCHER { 
  static DEV_BUILT_IN_MOS p1d;
  static MODEL_BUILT_IN_MOS5 p1(&p1d);
  static DISPATCHER<MODEL_CARD>::INSTALL
    d1(&model_dispatcher, "nmos5|pmos5", &p1);
}
/*--------------------------------------------------------------------------*/
void SDP_BUILT_IN_MOS5::init(const COMMON_COMPONENT* cc)
{
  assert(cc);
  SDP_BUILT_IN_MOS_BASE::init(cc);
  const COMMON_BUILT_IN_MOS* c = prechecked_cast<const COMMON_BUILT_IN_MOS*>(cc);
  assert(c);
  const MODEL_BUILT_IN_MOS5* m = prechecked_cast<const MODEL_BUILT_IN_MOS5*>(c->model());
  assert(m);
  const CARD_LIST* par_scope = m->scope();
  assert(par_scope);

      l_eff -= m->dl;
      w_eff -= m->dw;
      cgate = m->cox * w_eff * l_eff;
      double L = l_eff/MICRON2METER;
      double W = w_eff/MICRON2METER;
      double CoxWoverL = 1e-4 * m->cox * w_eff / l_eff;
  // adjust: override
    this->cgate = m->cox * w_eff * l_eff;
  // adjust: raw
  phi = m->phi(L, W, 0., par_scope);
  vfb = m->vfb(L, W, 0., par_scope);
  k1 = m->k1(L, W, 0., par_scope);
  k2 = m->k2(L, W, 0., par_scope);
  eta0 = m->eta0(L, W, 0., par_scope);
  etaB = m->etaB(L, W, 0., par_scope);
  mob0 = m->mob0(L, W, 0., par_scope);
  mob0B = m->mob0B(L, W, 0., par_scope);
  mobs0 = m->mobs0(L, W, 0., par_scope);
  mobsB = m->mobsB(L, W, 0., par_scope);
  mob20 = m->mob20(L, W, 0., par_scope);
  mob2B = m->mob2B(L, W, 0., par_scope);
  mob2G = m->mob2G(L, W, 0., par_scope);
  mob30 = m->mob30(L, W, 0., par_scope);
  mob3B = m->mob3B(L, W, 0., par_scope);
  mob3G = m->mob3G(L, W, 0., par_scope);
  mob40 = m->mob40(L, W, 0., par_scope);
  mob4B = m->mob4B(L, W, 0., par_scope);
  mob4G = m->mob4G(L, W, 0., par_scope);
  ua0 = m->ua0(L, W, 0., par_scope);
  uaB = m->uaB(L, W, 0., par_scope);
  ub0 = m->ub0(L, W, 0., par_scope);
  ubB = m->ubB(L, W, 0., par_scope);
  u10 = m->u10(L, W, 0., par_scope);
  u1B = m->u1B(L, W, 0., par_scope);
  u1D = m->u1D(L, W, 0., par_scope);
  n0 = m->n0(L, W, 0., par_scope);
  nB = m->nB(L, W, 0., par_scope);
  nD = m->nD(L, W, 0., par_scope);
  vof0 = m->vof0(L, W, 0., par_scope);
  vofB = m->vofB(L, W, 0., par_scope);
  vofD = m->vofD(L, W, 0., par_scope);
  ai0 = m->ai0(L, W, 0., par_scope);
  aiB = m->aiB(L, W, 0., par_scope);
  bi0 = m->bi0(L, W, 0., par_scope);
  biB = m->biB(L, W, 0., par_scope);
  vghigh = m->vghigh(L, W, 0., par_scope);
  vglow = m->vglow(L, W, 0., par_scope);
  // adjust: calculated
    beta0 = mob0 * CoxWoverL;
    beta0B = mob0B * CoxWoverL;
    betas0 = mobs0 * CoxWoverL;
    //betas0 = std::max(betas0, 1.01*beta0);
    betasB = mobsB * CoxWoverL;
    beta20 = mob20;
    beta2B = mob2B;
    beta2G = mob2G;
    beta30 = mob30 * CoxWoverL;
    beta3B = mob3B * CoxWoverL;
    beta3G = mob3G * CoxWoverL;
    beta40 = mob40 * CoxWoverL;
    beta4B = mob4B * CoxWoverL;
    beta4G = mob4G * CoxWoverL;
    Phis3 = sqrt(phi) * phi;
    One_Third_CoxWL = cgate / 3.0;
    Two_Third_CoxWL = 2.0 * One_Third_CoxWL;
  // code_post

      double tmp = betas0 - beta0 - beta0B * m->vbb;
      if ((-betasB * m->vbb) > tmp) {
	untested();
	betasB = -tmp / m->vbb;
      }
      Arg = betasB - beta0B - m->vdd * (beta3B - m->vdd * beta4B);
}
/*--------------------------------------------------------------------------*/
TDP_BUILT_IN_MOS5::TDP_BUILT_IN_MOS5(const DEV_BUILT_IN_MOS* d)
  :TDP_BUILT_IN_MOS_BASE(d)
{
}
/*--------------------------------------------------------------------------*/
MODEL_BUILT_IN_MOS5::MODEL_BUILT_IN_MOS5(const BASE_SUBCKT* p)
  :MODEL_BUILT_IN_MOS_BASE(p),
   phi(0.),
   vfb(0.),
   k1(0.),
   k2(0.),
   eta0(0.),
   etaB(0.),
   mob0(0.),
   mob0B(0.),
   mobs0(0.),
   mobsB(0.),
   mob20(0.),
   mob2B(0.),
   mob2G(0.),
   mob30(0.),
   mob3B(0.),
   mob3G(0.),
   mob40(0.),
   mob4B(0.),
   mob4G(0.),
   ua0(0.),
   uaB(0.),
   ub0(0.),
   ubB(0.),
   u10(0.),
   u1B(0.),
   u1D(0.),
   n0(0.),
   nB(0.),
   nD(0.),
   vof0(0.),
   vofB(0.),
   vofD(0.),
   ai0(0.),
   aiB(0.),
   bi0(0.),
   biB(0.),
   vghigh(0.),
   vglow(0.),
   dl_u(0.),
   dw_u(0.),
   tox_u(0.),
   vdd(0.),
   vgg(0.),
   vbb(0.),
   wdf(0.),
   dell(0.),
   temp_c(27.),
   xpart(0.),
   dl(NA),
   dw(NA),
   tox(NA),
   cox(NA),
   vdd2(NA),
   vgg2(NA),
   vbb2(NA),
   Vtm(NA)
{
  if (ENV::run_mode != rPRE_MAIN) {
    ++_count;
  }else{
  }
  set_default(&mjsw, NA);
  set_default(&pb, NA);
  set_default(&pbsw, NA);
  set_default(&cjo, 0.0);
  set_default(&mos_level, LEVEL);
}
/*--------------------------------------------------------------------------*/
MODEL_BUILT_IN_MOS5::MODEL_BUILT_IN_MOS5(const MODEL_BUILT_IN_MOS5& p)
  :MODEL_BUILT_IN_MOS_BASE(p),
   phi(p.phi),
   vfb(p.vfb),
   k1(p.k1),
   k2(p.k2),
   eta0(p.eta0),
   etaB(p.etaB),
   mob0(p.mob0),
   mob0B(p.mob0B),
   mobs0(p.mobs0),
   mobsB(p.mobsB),
   mob20(p.mob20),
   mob2B(p.mob2B),
   mob2G(p.mob2G),
   mob30(p.mob30),
   mob3B(p.mob3B),
   mob3G(p.mob3G),
   mob40(p.mob40),
   mob4B(p.mob4B),
   mob4G(p.mob4G),
   ua0(p.ua0),
   uaB(p.uaB),
   ub0(p.ub0),
   ubB(p.ubB),
   u10(p.u10),
   u1B(p.u1B),
   u1D(p.u1D),
   n0(p.n0),
   nB(p.nB),
   nD(p.nD),
   vof0(p.vof0),
   vofB(p.vofB),
   vofD(p.vofD),
   ai0(p.ai0),
   aiB(p.aiB),
   bi0(p.bi0),
   biB(p.biB),
   vghigh(p.vghigh),
   vglow(p.vglow),
   dl_u(p.dl_u),
   dw_u(p.dw_u),
   tox_u(p.tox_u),
   vdd(p.vdd),
   vgg(p.vgg),
   vbb(p.vbb),
   wdf(p.wdf),
   dell(p.dell),
   temp_c(p.temp_c),
   xpart(p.xpart),
   dl(p.dl),
   dw(p.dw),
   tox(p.tox),
   cox(p.cox),
   vdd2(p.vdd2),
   vgg2(p.vgg2),
   vbb2(p.vbb2),
   Vtm(p.Vtm)
{
  if (ENV::run_mode != rPRE_MAIN) {
    ++_count;
  }else{untested();//194
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS5::dev_type()const
{
  if (polarity == pN) {
    return "nmos5";
  }else if (polarity == pP) {
    return "pmos5";
  }else{untested();//235
    return MODEL_BUILT_IN_MOS_BASE::dev_type();
  }
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS5::set_dev_type(const std::string& new_type)
{
  if (Umatch(new_type, "nmos5 ")) {
    polarity = pN;
  }else if (Umatch(new_type, "pmos5 ")) {
    polarity = pP;
  }else{
    MODEL_BUILT_IN_MOS_BASE::set_dev_type(new_type);
  }
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS5::precalc_first()
{
    const CARD_LIST* par_scope = scope();
    assert(par_scope);
    MODEL_BUILT_IN_MOS_BASE::precalc_first();
    e_val(&(this->dl_u), 0., par_scope);
    e_val(&(this->dw_u), 0., par_scope);
    e_val(&(this->tox_u), 0., par_scope);
    e_val(&(this->vdd), 0., par_scope);
    e_val(&(this->vgg), 0., par_scope);
    e_val(&(this->vbb), 0., par_scope);
    e_val(&(this->wdf), 0., par_scope);
    e_val(&(this->dell), 0., par_scope);
    e_val(&(this->temp_c), 27., par_scope);
    e_val(&(this->xpart), 0., par_scope);
    // final adjust: code_pre
    // final adjust: override
    if (mjsw == NA) {
      mjsw = .33;
    }else{
    }
    if (pb == NA) {
      pb = 0.1;
    }else{
    }
    //pb = std::max(pb, 0.1);
    if (pbsw == NA) {
      pbsw = pb;
    }else{
    }
    //pbsw = std::max(pbsw, 0.1);
    cmodel = ((!cmodel)?1:cmodel);
    // final adjust: raw
    e_val(&(this->dl_u), 0., par_scope);
    e_val(&(this->dw_u), 0., par_scope);
    e_val(&(this->tox_u), 0., par_scope);
    //this->tox_u = std::max(tox_u, 1e-20);
    e_val(&(this->vdd), 0., par_scope);
    e_val(&(this->vgg), 0., par_scope);
    e_val(&(this->vbb), 0., par_scope);
    e_val(&(this->wdf), 0., par_scope);
    e_val(&(this->dell), 0., par_scope);
    e_val(&(this->temp_c), 27., par_scope);
    e_val(&(this->xpart), 0., par_scope);
    // final adjust: mid
    // final adjust: calculated
    dl = dl_u*MICRON2METER;
    dw = dw_u*MICRON2METER;
    tox = tox_u*MICRON2METER;
    cox = 3.453e-11 /*E_OX*/ / tox;
    vdd2 = 2 * vdd;
    vgg2 = 2 * vgg;
    vbb2 = 2 * vbb;
    Vtm = 8.625e-5 /*K/Q*/ * (temp_c + P_CELSIUS0 -.15);
    // final adjust: post
    // final adjust: done
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS5::precalc_last()
{
    MODEL_BUILT_IN_MOS_BASE::precalc_last();
}
/*--------------------------------------------------------------------------*/
SDP_CARD* MODEL_BUILT_IN_MOS5::new_sdp(COMMON_COMPONENT* c)const
{
  assert(c);
  if (COMMON_BUILT_IN_MOS* cc = dynamic_cast<COMMON_BUILT_IN_MOS*>(c)) {
    if (cc->_sdp) {
      cc->_sdp->init(cc);
      return cc->_sdp;
    }else{
      delete cc->_sdp;
      return new SDP_BUILT_IN_MOS5(c);
    }
  }else{
    return MODEL_BUILT_IN_MOS_BASE::new_sdp(c);
  }
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS5::set_param_by_index(int i, std::string& value, int offset)
{
  switch (MODEL_BUILT_IN_MOS5::param_count() - 1 - i) {
  case 0: level = value; break; //5
  case 1: unreachable(); break;
  case 2: unreachable(); break;
  case 3: unreachable(); break;
  case 4: unreachable(); break;
  case 5: unreachable(); break;
  case 6: mos_level = value; break;
  case 7: phi.set_nom(value); break;
  case 8: phi.set_w(value); break;
  case 9: phi.set_l(value); break;
  case 10: phi.set_p(value); break;
  case 11: vfb.set_nom(value); break;
  case 12: vfb.set_w(value); break;
  case 13: vfb.set_l(value); break;
  case 14: vfb.set_p(value); break;
  case 15: k1.set_nom(value); break;
  case 16: k1.set_w(value); break;
  case 17: k1.set_l(value); break;
  case 18: k1.set_p(value); break;
  case 19: k2.set_nom(value); break;
  case 20: k2.set_w(value); break;
  case 21: k2.set_l(value); break;
  case 22: k2.set_p(value); break;
  case 23: eta0.set_nom(value); break;
  case 24: eta0.set_w(value); break;
  case 25: eta0.set_l(value); break;
  case 26: eta0.set_p(value); break;
  case 27: etaB.set_nom(value); break;
  case 28: etaB.set_w(value); break;
  case 29: etaB.set_l(value); break;
  case 30: etaB.set_p(value); break;
  case 31: mob0.set_nom(value); break;
  case 32: mob0.set_w(value); break;
  case 33: mob0.set_l(value); break;
  case 34: mob0.set_p(value); break;
  case 35: mob0B.set_nom(value); break;
  case 36: mob0B.set_w(value); break;
  case 37: mob0B.set_l(value); break;
  case 38: mob0B.set_p(value); break;
  case 39: mobs0.set_nom(value); break;
  case 40: mobs0.set_w(value); break;
  case 41: mobs0.set_l(value); break;
  case 42: mobs0.set_p(value); break;
  case 43: mobsB.set_nom(value); break;
  case 44: mobsB.set_w(value); break;
  case 45: mobsB.set_l(value); break;
  case 46: mobsB.set_p(value); break;
  case 47: mob20.set_nom(value); break;
  case 48: mob20.set_w(value); break;
  case 49: mob20.set_l(value); break;
  case 50: mob20.set_p(value); break;
  case 51: mob2B.set_nom(value); break;
  case 52: mob2B.set_w(value); break;
  case 53: mob2B.set_l(value); break;
  case 54: mob2B.set_p(value); break;
  case 55: mob2G.set_nom(value); break;
  case 56: mob2G.set_w(value); break;
  case 57: mob2G.set_l(value); break;
  case 58: mob2G.set_p(value); break;
  case 59: mob30.set_nom(value); break;
  case 60: mob30.set_w(value); break;
  case 61: mob30.set_l(value); break;
  case 62: mob30.set_p(value); break;
  case 63: mob3B.set_nom(value); break;
  case 64: mob3B.set_w(value); break;
  case 65: mob3B.set_l(value); break;
  case 66: mob3B.set_p(value); break;
  case 67: mob3G.set_nom(value); break;
  case 68: mob3G.set_w(value); break;
  case 69: mob3G.set_l(value); break;
  case 70: mob3G.set_p(value); break;
  case 71: mob40.set_nom(value); break;
  case 72: mob40.set_w(value); break;
  case 73: mob40.set_l(value); break;
  case 74: mob40.set_p(value); break;
  case 75: mob4B.set_nom(value); break;
  case 76: mob4B.set_w(value); break;
  case 77: mob4B.set_l(value); break;
  case 78: mob4B.set_p(value); break;
  case 79: mob4G.set_nom(value); break;
  case 80: mob4G.set_w(value); break;
  case 81: mob4G.set_l(value); break;
  case 82: mob4G.set_p(value); break;
  case 83: ua0.set_nom(value); break;
  case 84: ua0.set_w(value); break;
  case 85: ua0.set_l(value); break;
  case 86: ua0.set_p(value); break;
  case 87: uaB.set_nom(value); break;
  case 88: uaB.set_w(value); break;
  case 89: uaB.set_l(value); break;
  case 90: uaB.set_p(value); break;
  case 91: ub0.set_nom(value); break;
  case 92: ub0.set_w(value); break;
  case 93: ub0.set_l(value); break;
  case 94: ub0.set_p(value); break;
  case 95: ubB.set_nom(value); break;
  case 96: ubB.set_w(value); break;
  case 97: ubB.set_l(value); break;
  case 98: ubB.set_p(value); break;
  case 99: u10.set_nom(value); break;
  case 100: u10.set_w(value); break;
  case 101: u10.set_l(value); break;
  case 102: u10.set_p(value); break;
  case 103: u1B.set_nom(value); break;
  case 104: u1B.set_w(value); break;
  case 105: u1B.set_l(value); break;
  case 106: u1B.set_p(value); break;
  case 107: u1D.set_nom(value); break;
  case 108: u1D.set_w(value); break;
  case 109: u1D.set_l(value); break;
  case 110: u1D.set_p(value); break;
  case 111: n0.set_nom(value); break;
  case 112: n0.set_w(value); break;
  case 113: n0.set_l(value); break;
  case 114: n0.set_p(value); break;
  case 115: nB.set_nom(value); break;
  case 116: nB.set_w(value); break;
  case 117: nB.set_l(value); break;
  case 118: nB.set_p(value); break;
  case 119: nD.set_nom(value); break;
  case 120: nD.set_w(value); break;
  case 121: nD.set_l(value); break;
  case 122: nD.set_p(value); break;
  case 123: vof0.set_nom(value); break;
  case 124: vof0.set_w(value); break;
  case 125: vof0.set_l(value); break;
  case 126: vof0.set_p(value); break;
  case 127: vofB.set_nom(value); break;
  case 128: vofB.set_w(value); break;
  case 129: vofB.set_l(value); break;
  case 130: vofB.set_p(value); break;
  case 131: vofD.set_nom(value); break;
  case 132: vofD.set_w(value); break;
  case 133: vofD.set_l(value); break;
  case 134: vofD.set_p(value); break;
  case 135: ai0.set_nom(value); break;
  case 136: ai0.set_w(value); break;
  case 137: ai0.set_l(value); break;
  case 138: ai0.set_p(value); break;
  case 139: aiB.set_nom(value); break;
  case 140: aiB.set_w(value); break;
  case 141: aiB.set_l(value); break;
  case 142: aiB.set_p(value); break;
  case 143: bi0.set_nom(value); break;
  case 144: bi0.set_w(value); break;
  case 145: bi0.set_l(value); break;
  case 146: bi0.set_p(value); break;
  case 147: biB.set_nom(value); break;
  case 148: biB.set_w(value); break;
  case 149: biB.set_l(value); break;
  case 150: biB.set_p(value); break;
  case 151: vghigh.set_nom(value); break;
  case 152: vghigh.set_w(value); break;
  case 153: vghigh.set_l(value); break;
  case 154: vghigh.set_p(value); break;
  case 155: vglow.set_nom(value); break;
  case 156: vglow.set_w(value); break;
  case 157: vglow.set_l(value); break;
  case 158: vglow.set_p(value); break;
  case 159: dl_u = value; break;
  case 160: dw_u = value; break;
  case 161: tox_u = value; break;
  case 162: vdd = value; break;
  case 163: vgg = value; break;
  case 164: vbb = value; break;
  case 165: wdf = value; break;
  case 166: dell = value; break;
  case 167: temp_c = value; break;
  case 168: xpart = value; break;
  default: MODEL_BUILT_IN_MOS_BASE::set_param_by_index(i, value, offset); break;
  }
}
/*--------------------------------------------------------------------------*/
bool MODEL_BUILT_IN_MOS5::param_is_printable(int i)const
{
  switch (MODEL_BUILT_IN_MOS5::param_count() - 1 - i) {
  case 0:  return (true);
  case 1:  return (false);
  case 2:  return (false);
  case 3:  return (false);
  case 4:  return (false);
  case 5:  return (false);
  case 6:  return (mos_level != LEVEL);
  case 7:  return (true);
  case 8:  return (phi.w_has_value());
  case 9:  return (phi.l_has_value());
  case 10:  return (phi.p_has_value());
  case 11:  return (true);
  case 12:  return (vfb.w_has_value());
  case 13:  return (vfb.l_has_value());
  case 14:  return (vfb.p_has_value());
  case 15:  return (true);
  case 16:  return (k1.w_has_value());
  case 17:  return (k1.l_has_value());
  case 18:  return (k1.p_has_value());
  case 19:  return (true);
  case 20:  return (k2.w_has_value());
  case 21:  return (k2.l_has_value());
  case 22:  return (k2.p_has_value());
  case 23:  return (true);
  case 24:  return (eta0.w_has_value());
  case 25:  return (eta0.l_has_value());
  case 26:  return (eta0.p_has_value());
  case 27:  return (true);
  case 28:  return (etaB.w_has_value());
  case 29:  return (etaB.l_has_value());
  case 30:  return (etaB.p_has_value());
  case 31:  return (true);
  case 32:  return (mob0.w_has_value());
  case 33:  return (mob0.l_has_value());
  case 34:  return (mob0.p_has_value());
  case 35:  return (true);
  case 36:  return (mob0B.w_has_value());
  case 37:  return (mob0B.l_has_value());
  case 38:  return (mob0B.p_has_value());
  case 39:  return (true);
  case 40:  return (mobs0.w_has_value());
  case 41:  return (mobs0.l_has_value());
  case 42:  return (mobs0.p_has_value());
  case 43:  return (true);
  case 44:  return (mobsB.w_has_value());
  case 45:  return (mobsB.l_has_value());
  case 46:  return (mobsB.p_has_value());
  case 47:  return (true);
  case 48:  return (mob20.w_has_value());
  case 49:  return (mob20.l_has_value());
  case 50:  return (mob20.p_has_value());
  case 51:  return (true);
  case 52:  return (mob2B.w_has_value());
  case 53:  return (mob2B.l_has_value());
  case 54:  return (mob2B.p_has_value());
  case 55:  return (true);
  case 56:  return (mob2G.w_has_value());
  case 57:  return (mob2G.l_has_value());
  case 58:  return (mob2G.p_has_value());
  case 59:  return (true);
  case 60:  return (mob30.w_has_value());
  case 61:  return (mob30.l_has_value());
  case 62:  return (mob30.p_has_value());
  case 63:  return (true);
  case 64:  return (mob3B.w_has_value());
  case 65:  return (mob3B.l_has_value());
  case 66:  return (mob3B.p_has_value());
  case 67:  return (true);
  case 68:  return (mob3G.w_has_value());
  case 69:  return (mob3G.l_has_value());
  case 70:  return (mob3G.p_has_value());
  case 71:  return (true);
  case 72:  return (mob40.w_has_value());
  case 73:  return (mob40.l_has_value());
  case 74:  return (mob40.p_has_value());
  case 75:  return (true);
  case 76:  return (mob4B.w_has_value());
  case 77:  return (mob4B.l_has_value());
  case 78:  return (mob4B.p_has_value());
  case 79:  return (true);
  case 80:  return (mob4G.w_has_value());
  case 81:  return (mob4G.l_has_value());
  case 82:  return (mob4G.p_has_value());
  case 83:  return (true);
  case 84:  return (ua0.w_has_value());
  case 85:  return (ua0.l_has_value());
  case 86:  return (ua0.p_has_value());
  case 87:  return (true);
  case 88:  return (uaB.w_has_value());
  case 89:  return (uaB.l_has_value());
  case 90:  return (uaB.p_has_value());
  case 91:  return (true);
  case 92:  return (ub0.w_has_value());
  case 93:  return (ub0.l_has_value());
  case 94:  return (ub0.p_has_value());
  case 95:  return (true);
  case 96:  return (ubB.w_has_value());
  case 97:  return (ubB.l_has_value());
  case 98:  return (ubB.p_has_value());
  case 99:  return (true);
  case 100:  return (u10.w_has_value());
  case 101:  return (u10.l_has_value());
  case 102:  return (u10.p_has_value());
  case 103:  return (true);
  case 104:  return (u1B.w_has_value());
  case 105:  return (u1B.l_has_value());
  case 106:  return (u1B.p_has_value());
  case 107:  return (true);
  case 108:  return (u1D.w_has_value());
  case 109:  return (u1D.l_has_value());
  case 110:  return (u1D.p_has_value());
  case 111:  return (true);
  case 112:  return (n0.w_has_value());
  case 113:  return (n0.l_has_value());
  case 114:  return (n0.p_has_value());
  case 115:  return (true);
  case 116:  return (nB.w_has_value());
  case 117:  return (nB.l_has_value());
  case 118:  return (nB.p_has_value());
  case 119:  return (true);
  case 120:  return (nD.w_has_value());
  case 121:  return (nD.l_has_value());
  case 122:  return (nD.p_has_value());
  case 123:  return (true);
  case 124:  return (vof0.w_has_value());
  case 125:  return (vof0.l_has_value());
  case 126:  return (vof0.p_has_value());
  case 127:  return (true);
  case 128:  return (vofB.w_has_value());
  case 129:  return (vofB.l_has_value());
  case 130:  return (vofB.p_has_value());
  case 131:  return (true);
  case 132:  return (vofD.w_has_value());
  case 133:  return (vofD.l_has_value());
  case 134:  return (vofD.p_has_value());
  case 135:  return (true);
  case 136:  return (ai0.w_has_value());
  case 137:  return (ai0.l_has_value());
  case 138:  return (ai0.p_has_value());
  case 139:  return (true);
  case 140:  return (aiB.w_has_value());
  case 141:  return (aiB.l_has_value());
  case 142:  return (aiB.p_has_value());
  case 143:  return (true);
  case 144:  return (bi0.w_has_value());
  case 145:  return (bi0.l_has_value());
  case 146:  return (bi0.p_has_value());
  case 147:  return (true);
  case 148:  return (biB.w_has_value());
  case 149:  return (biB.l_has_value());
  case 150:  return (biB.p_has_value());
  case 151:  return (true);
  case 152:  return (vghigh.w_has_value());
  case 153:  return (vghigh.l_has_value());
  case 154:  return (vghigh.p_has_value());
  case 155:  return (true);
  case 156:  return (vglow.w_has_value());
  case 157:  return (vglow.l_has_value());
  case 158:  return (vglow.p_has_value());
  case 159:  return (true);
  case 160:  return (true);
  case 161:  return (true);
  case 162:  return (true);
  case 163:  return (true);
  case 164:  return (true);
  case 165:  return (true);
  case 166:  return (true);
  case 167:  return (true);
  case 168:  return (true);
  default: return MODEL_BUILT_IN_MOS_BASE::param_is_printable(i);
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS5::param_name(int i)const
{
  switch (MODEL_BUILT_IN_MOS5::param_count() - 1 - i) {
  case 0:  return "level";
  case 1:  return "=====";
  case 2:  return "=====";
  case 3:  return "=====";
  case 4:  return "=====";
  case 5:  return "=====";
  case 6:  return "diodelevel";
  case 7:  return "phi";
  case 8:  return "wphi";
  case 9:  return "lphi";
  case 10:  return "pphi";
  case 11:  return "vfb";
  case 12:  return "wvfb";
  case 13:  return "lvfb";
  case 14:  return "pvfb";
  case 15:  return "k1";
  case 16:  return "wk1";
  case 17:  return "lk1";
  case 18:  return "pk1";
  case 19:  return "k2";
  case 20:  return "wk2";
  case 21:  return "lk2";
  case 22:  return "pk2";
  case 23:  return "eta0";
  case 24:  return "weta0";
  case 25:  return "leta0";
  case 26:  return "peta0";
  case 27:  return "etab";
  case 28:  return "wetab";
  case 29:  return "letab";
  case 30:  return "petab";
  case 31:  return "mu0";
  case 32:  return "wmu0";
  case 33:  return "lmu0";
  case 34:  return "pmu0";
  case 35:  return "mu0b";
  case 36:  return "wmu0b";
  case 37:  return "lmu0b";
  case 38:  return "pmu0b";
  case 39:  return "mus0";
  case 40:  return "wmus0";
  case 41:  return "lmus0";
  case 42:  return "pmus0";
  case 43:  return "musb";
  case 44:  return "wmusb";
  case 45:  return "lmusb";
  case 46:  return "pmusb";
  case 47:  return "mu20";
  case 48:  return "wmu20";
  case 49:  return "lmu20";
  case 50:  return "pmu20";
  case 51:  return "mu2b";
  case 52:  return "wmu2b";
  case 53:  return "lmu2b";
  case 54:  return "pmu2b";
  case 55:  return "mu2g";
  case 56:  return "wmu2g";
  case 57:  return "lmu2g";
  case 58:  return "pmu2g";
  case 59:  return "mu30";
  case 60:  return "wmu30";
  case 61:  return "lmu30";
  case 62:  return "pmu30";
  case 63:  return "mu3b";
  case 64:  return "wmu3b";
  case 65:  return "lmu3b";
  case 66:  return "pmu3b";
  case 67:  return "mu3g";
  case 68:  return "wmu3g";
  case 69:  return "lmu3g";
  case 70:  return "pmu3g";
  case 71:  return "mu40";
  case 72:  return "wmu40";
  case 73:  return "lmu40";
  case 74:  return "pmu40";
  case 75:  return "mu4b";
  case 76:  return "wmu4b";
  case 77:  return "lmu4b";
  case 78:  return "pmu4b";
  case 79:  return "mu4g";
  case 80:  return "wmu4g";
  case 81:  return "lmu4g";
  case 82:  return "pmu4g";
  case 83:  return "ua0";
  case 84:  return "wua0";
  case 85:  return "lua0";
  case 86:  return "pua0";
  case 87:  return "uab";
  case 88:  return "wuab";
  case 89:  return "luab";
  case 90:  return "puab";
  case 91:  return "ub0";
  case 92:  return "wub0";
  case 93:  return "lub0";
  case 94:  return "pub0";
  case 95:  return "ubb";
  case 96:  return "wubb";
  case 97:  return "lubb";
  case 98:  return "pubb";
  case 99:  return "u10";
  case 100:  return "wu10";
  case 101:  return "lu10";
  case 102:  return "pu10";
  case 103:  return "u1b";
  case 104:  return "wu1b";
  case 105:  return "lu1b";
  case 106:  return "pu1b";
  case 107:  return "u1d";
  case 108:  return "wu1d";
  case 109:  return "lu1d";
  case 110:  return "pu1d";
  case 111:  return "n0";
  case 112:  return "wn0";
  case 113:  return "ln0";
  case 114:  return "pn0";
  case 115:  return "nb";
  case 116:  return "wnb";
  case 117:  return "lnb";
  case 118:  return "pnb";
  case 119:  return "nd";
  case 120:  return "wnd";
  case 121:  return "lnd";
  case 122:  return "pnd";
  case 123:  return "vof0";
  case 124:  return "wvof0";
  case 125:  return "lvof0";
  case 126:  return "pvof0";
  case 127:  return "vofb";
  case 128:  return "wvofb";
  case 129:  return "lvofb";
  case 130:  return "pvofb";
  case 131:  return "vofd";
  case 132:  return "wvofd";
  case 133:  return "lvofd";
  case 134:  return "pvofd";
  case 135:  return "ai0";
  case 136:  return "wai0";
  case 137:  return "lai0";
  case 138:  return "pai0";
  case 139:  return "aib";
  case 140:  return "waib";
  case 141:  return "laib";
  case 142:  return "paib";
  case 143:  return "bi0";
  case 144:  return "wbi0";
  case 145:  return "lbi0";
  case 146:  return "pbi0";
  case 147:  return "bib";
  case 148:  return "wbib";
  case 149:  return "lbib";
  case 150:  return "pbib";
  case 151:  return "vghigh";
  case 152:  return "wvghigh";
  case 153:  return "lvghigh";
  case 154:  return "pvghigh";
  case 155:  return "vglow";
  case 156:  return "wvglow";
  case 157:  return "lvglow";
  case 158:  return "pvglow";
  case 159:  return "dl";
  case 160:  return "dw";
  case 161:  return "tox";
  case 162:  return "vdd";
  case 163:  return "vgg";
  case 164:  return "vbb";
  case 165:  return "wdf";
  case 166:  return "dell";
  case 167:  return "temp";
  case 168:  return "xpart";
  default: return MODEL_BUILT_IN_MOS_BASE::param_name(i);
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS5::param_name(int i, int j)const
{
  if (j == 0) {
    return param_name(i);
  }else if (j == 1) {
    switch (MODEL_BUILT_IN_MOS5::param_count() - 1 - i) {
    case 0:  return "";
    case 1:  return "";
    case 2:  return "";
    case 3:  return "";
    case 4:  return "";
    case 5:  return "";
    case 6:  return "";
    case 7:  return "";
    case 8:  return "";
    case 9:  return "";
    case 10:  return "";
    case 11:  return "";
    case 12:  return "";
    case 13:  return "";
    case 14:  return "";
    case 15:  return "";
    case 16:  return "";
    case 17:  return "";
    case 18:  return "";
    case 19:  return "";
    case 20:  return "";
    case 21:  return "";
    case 22:  return "";
    case 23:  return "";
    case 24:  return "";
    case 25:  return "";
    case 26:  return "";
    case 27:  return "";
    case 28:  return "";
    case 29:  return "";
    case 30:  return "";
    case 31:  return "";
    case 32:  return "";
    case 33:  return "";
    case 34:  return "";
    case 35:  return "";
    case 36:  return "";
    case 37:  return "";
    case 38:  return "";
    case 39:  return "";
    case 40:  return "";
    case 41:  return "";
    case 42:  return "";
    case 43:  return "";
    case 44:  return "";
    case 45:  return "";
    case 46:  return "";
    case 47:  return "";
    case 48:  return "";
    case 49:  return "";
    case 50:  return "";
    case 51:  return "";
    case 52:  return "";
    case 53:  return "";
    case 54:  return "";
    case 55:  return "";
    case 56:  return "";
    case 57:  return "";
    case 58:  return "";
    case 59:  return "";
    case 60:  return "";
    case 61:  return "";
    case 62:  return "";
    case 63:  return "";
    case 64:  return "";
    case 65:  return "";
    case 66:  return "";
    case 67:  return "";
    case 68:  return "";
    case 69:  return "";
    case 70:  return "";
    case 71:  return "";
    case 72:  return "";
    case 73:  return "";
    case 74:  return "";
    case 75:  return "";
    case 76:  return "";
    case 77:  return "";
    case 78:  return "";
    case 79:  return "";
    case 80:  return "";
    case 81:  return "";
    case 82:  return "";
    case 83:  return "";
    case 84:  return "";
    case 85:  return "";
    case 86:  return "";
    case 87:  return "";
    case 88:  return "";
    case 89:  return "";
    case 90:  return "";
    case 91:  return "";
    case 92:  return "";
    case 93:  return "";
    case 94:  return "";
    case 95:  return "";
    case 96:  return "";
    case 97:  return "";
    case 98:  return "";
    case 99:  return "";
    case 100:  return "";
    case 101:  return "";
    case 102:  return "";
    case 103:  return "";
    case 104:  return "";
    case 105:  return "";
    case 106:  return "";
    case 107:  return "";
    case 108:  return "";
    case 109:  return "";
    case 110:  return "";
    case 111:  return "";
    case 112:  return "";
    case 113:  return "";
    case 114:  return "";
    case 115:  return "";
    case 116:  return "";
    case 117:  return "";
    case 118:  return "";
    case 119:  return "";
    case 120:  return "";
    case 121:  return "";
    case 122:  return "";
    case 123:  return "";
    case 124:  return "";
    case 125:  return "";
    case 126:  return "";
    case 127:  return "";
    case 128:  return "";
    case 129:  return "";
    case 130:  return "";
    case 131:  return "";
    case 132:  return "";
    case 133:  return "";
    case 134:  return "";
    case 135:  return "";
    case 136:  return "";
    case 137:  return "";
    case 138:  return "";
    case 139:  return "";
    case 140:  return "";
    case 141:  return "";
    case 142:  return "";
    case 143:  return "";
    case 144:  return "";
    case 145:  return "";
    case 146:  return "";
    case 147:  return "";
    case 148:  return "";
    case 149:  return "";
    case 150:  return "";
    case 151:  return "";
    case 152:  return "";
    case 153:  return "";
    case 154:  return "";
    case 155:  return "";
    case 156:  return "";
    case 157:  return "";
    case 158:  return "";
    case 159:  return "";
    case 160:  return "";
    case 161:  return "";
    case 162:  return "";
    case 163:  return "";
    case 164:  return "";
    case 165:  return "";
    case 166:  return "";
    case 167:  return "";
    case 168:  return "";
    default: return MODEL_BUILT_IN_MOS_BASE::param_name(i, j);
    }
  }else if (i < 169) {
    return "";
  }else{
    return MODEL_BUILT_IN_MOS_BASE::param_name(i, j);
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS5::param_value(int i)const
{
  switch (MODEL_BUILT_IN_MOS5::param_count() - 1 - i) {
  case 0:  return "5";
  case 1:  unreachable(); return "";
  case 2:  unreachable(); return "";
  case 3:  unreachable(); return "";
  case 4:  unreachable(); return "";
  case 5:  unreachable(); return "";
  case 6:  return mos_level.string();
  case 7:  return phi.string();
  case 8:  return phi.w_string();
  case 9:  return phi.l_string();
  case 10:  return phi.p_string();
  case 11:  return vfb.string();
  case 12:  return vfb.w_string();
  case 13:  return vfb.l_string();
  case 14:  return vfb.p_string();
  case 15:  return k1.string();
  case 16:  return k1.w_string();
  case 17:  return k1.l_string();
  case 18:  return k1.p_string();
  case 19:  return k2.string();
  case 20:  return k2.w_string();
  case 21:  return k2.l_string();
  case 22:  return k2.p_string();
  case 23:  return eta0.string();
  case 24:  return eta0.w_string();
  case 25:  return eta0.l_string();
  case 26:  return eta0.p_string();
  case 27:  return etaB.string();
  case 28:  return etaB.w_string();
  case 29:  return etaB.l_string();
  case 30:  return etaB.p_string();
  case 31:  return mob0.string();
  case 32:  return mob0.w_string();
  case 33:  return mob0.l_string();
  case 34:  return mob0.p_string();
  case 35:  return mob0B.string();
  case 36:  return mob0B.w_string();
  case 37:  return mob0B.l_string();
  case 38:  return mob0B.p_string();
  case 39:  return mobs0.string();
  case 40:  return mobs0.w_string();
  case 41:  return mobs0.l_string();
  case 42:  return mobs0.p_string();
  case 43:  return mobsB.string();
  case 44:  return mobsB.w_string();
  case 45:  return mobsB.l_string();
  case 46:  return mobsB.p_string();
  case 47:  return mob20.string();
  case 48:  return mob20.w_string();
  case 49:  return mob20.l_string();
  case 50:  return mob20.p_string();
  case 51:  return mob2B.string();
  case 52:  return mob2B.w_string();
  case 53:  return mob2B.l_string();
  case 54:  return mob2B.p_string();
  case 55:  return mob2G.string();
  case 56:  return mob2G.w_string();
  case 57:  return mob2G.l_string();
  case 58:  return mob2G.p_string();
  case 59:  return mob30.string();
  case 60:  return mob30.w_string();
  case 61:  return mob30.l_string();
  case 62:  return mob30.p_string();
  case 63:  return mob3B.string();
  case 64:  return mob3B.w_string();
  case 65:  return mob3B.l_string();
  case 66:  return mob3B.p_string();
  case 67:  return mob3G.string();
  case 68:  return mob3G.w_string();
  case 69:  return mob3G.l_string();
  case 70:  return mob3G.p_string();
  case 71:  return mob40.string();
  case 72:  return mob40.w_string();
  case 73:  return mob40.l_string();
  case 74:  return mob40.p_string();
  case 75:  return mob4B.string();
  case 76:  return mob4B.w_string();
  case 77:  return mob4B.l_string();
  case 78:  return mob4B.p_string();
  case 79:  return mob4G.string();
  case 80:  return mob4G.w_string();
  case 81:  return mob4G.l_string();
  case 82:  return mob4G.p_string();
  case 83:  return ua0.string();
  case 84:  return ua0.w_string();
  case 85:  return ua0.l_string();
  case 86:  return ua0.p_string();
  case 87:  return uaB.string();
  case 88:  return uaB.w_string();
  case 89:  return uaB.l_string();
  case 90:  return uaB.p_string();
  case 91:  return ub0.string();
  case 92:  return ub0.w_string();
  case 93:  return ub0.l_string();
  case 94:  return ub0.p_string();
  case 95:  return ubB.string();
  case 96:  return ubB.w_string();
  case 97:  return ubB.l_string();
  case 98:  return ubB.p_string();
  case 99:  return u10.string();
  case 100:  return u10.w_string();
  case 101:  return u10.l_string();
  case 102:  return u10.p_string();
  case 103:  return u1B.string();
  case 104:  return u1B.w_string();
  case 105:  return u1B.l_string();
  case 106:  return u1B.p_string();
  case 107:  return u1D.string();
  case 108:  return u1D.w_string();
  case 109:  return u1D.l_string();
  case 110:  return u1D.p_string();
  case 111:  return n0.string();
  case 112:  return n0.w_string();
  case 113:  return n0.l_string();
  case 114:  return n0.p_string();
  case 115:  return nB.string();
  case 116:  return nB.w_string();
  case 117:  return nB.l_string();
  case 118:  return nB.p_string();
  case 119:  return nD.string();
  case 120:  return nD.w_string();
  case 121:  return nD.l_string();
  case 122:  return nD.p_string();
  case 123:  return vof0.string();
  case 124:  return vof0.w_string();
  case 125:  return vof0.l_string();
  case 126:  return vof0.p_string();
  case 127:  return vofB.string();
  case 128:  return vofB.w_string();
  case 129:  return vofB.l_string();
  case 130:  return vofB.p_string();
  case 131:  return vofD.string();
  case 132:  return vofD.w_string();
  case 133:  return vofD.l_string();
  case 134:  return vofD.p_string();
  case 135:  return ai0.string();
  case 136:  return ai0.w_string();
  case 137:  return ai0.l_string();
  case 138:  return ai0.p_string();
  case 139:  return aiB.string();
  case 140:  return aiB.w_string();
  case 141:  return aiB.l_string();
  case 142:  return aiB.p_string();
  case 143:  return bi0.string();
  case 144:  return bi0.w_string();
  case 145:  return bi0.l_string();
  case 146:  return bi0.p_string();
  case 147:  return biB.string();
  case 148:  return biB.w_string();
  case 149:  return biB.l_string();
  case 150:  return biB.p_string();
  case 151:  return vghigh.string();
  case 152:  return vghigh.w_string();
  case 153:  return vghigh.l_string();
  case 154:  return vghigh.p_string();
  case 155:  return vglow.string();
  case 156:  return vglow.w_string();
  case 157:  return vglow.l_string();
  case 158:  return vglow.p_string();
  case 159:  return dl_u.string();
  case 160:  return dw_u.string();
  case 161:  return tox_u.string();
  case 162:  return vdd.string();
  case 163:  return vgg.string();
  case 164:  return vbb.string();
  case 165:  return wdf.string();
  case 166:  return dell.string();
  case 167:  return temp_c.string();
  case 168:  return xpart.string();
  default: return MODEL_BUILT_IN_MOS_BASE::param_value(i);
  }
}
/*--------------------------------------------------------------------------*/
bool MODEL_BUILT_IN_MOS5::is_valid(const COMPONENT* d)const
{
  assert(d);
  return MODEL_BUILT_IN_MOS_BASE::is_valid(d);
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS5::tr_eval(COMPONENT* brh)const
{
  DEV_BUILT_IN_MOS* d = prechecked_cast<DEV_BUILT_IN_MOS*>(brh);
  assert(d);
  const COMMON_BUILT_IN_MOS* c = prechecked_cast<const COMMON_BUILT_IN_MOS*>(d->common());
  assert(c);
  const SDP_BUILT_IN_MOS5* s = prechecked_cast<const SDP_BUILT_IN_MOS5*>(c->sdp());
  assert(s);
  const MODEL_BUILT_IN_MOS5* m = this;

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    trace3("", d->vds, d->vgs, d->vbs);
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
    d->reverse_if_needed();
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    trace4("", c->lo, m->dl, c->wo, m->dw);
    
    double Vbs = std::max(m->vbb2, d->vbs);
    double Vgs = std::min(m->vgg2, d->vgs);
    double Vds = std::min(m->vdd2, d->vds);
    trace3("", Vbs, Vgs, Vds);
    
    /* Threshold Voltage. */
    double Phisb, dPhisb_dVb, T1s, dT1s_dVb;
    if (Vbs <= 0.0) {
      d->sbfwd = false;
      Phisb = s->phi - Vbs;
      dPhisb_dVb = -1.0;
      T1s = sqrt(Phisb);
      dT1s_dVb = -0.5 / T1s;
      trace4("-", Phisb, dPhisb_dVb, T1s, dT1s_dVb);
    }else{
      d->sbfwd = true;
      double tmp = s->phi / (s->phi + Vbs);
      Phisb = s->phi * tmp;
      dPhisb_dVb = -tmp * tmp;
      T1s = s->Phis3 / (s->phi + 0.5 * Vbs);
      dT1s_dVb = -0.5 * T1s * T1s / s->Phis3;
      trace4("+", Phisb, dPhisb_dVb, T1s, dT1s_dVb);
    }
    
    double Eta = s->eta0 + s->etaB * Vbs;
    double Ua = s->ua0 + s->uaB * Vbs;
    double Ub = s->ub0 + s->ubB * Vbs;
    double U1s = s->u10 + s->u1B * Vbs;
    trace4("", Eta, Ua, Ub, U1s);
    
    d->von = s->vfb + s->phi + s->k1*T1s - s->k2*Phisb - Eta*Vds;
    double dVth_dVd = -Eta;
    double dVth_dVb = s->k1 * dT1s_dVb + s->k2 - s->etaB * Vds;
    d->vgst = Vgs - d->von;
    trace4("", d->von, dVth_dVd, dVth_dVb, d->vgst);
    
    double Aa, dAa_dVb, Inv_Aa;
    {
      double tmp = 1.0 / (1.744 + 0.8364 * Phisb);
      double Gg = 1.0 - tmp;
      double dGg_dVb = 0.8364 * tmp * tmp * dPhisb_dVb;
      double T0 = Gg / T1s;
      trace4("", tmp, Gg, dGg_dVb, T0);
      double tmp1 = 0.5 * T0 * s->k1;
      Aa = 1.0 + tmp1;
      dAa_dVb = (Aa - 1.0) * (dGg_dVb / Gg - dT1s_dVb / T1s);
      Inv_Aa = 1.0 / Aa;
      trace4("", tmp1, Aa, dAa_dVb, Inv_Aa);
    }
    
    trace3("", s->vghigh, s->vglow, d->vgst);
    
    double Exp0, Exp1, n, Vgeff, dVgeff_dVg, dVgeff_dVd, dVgeff_dVb;
    if ((d->vgst >= s->vghigh) || (s->n0 == 0.0)) {
      Exp0 = NOT_VALID;
      Exp1 = NOT_VALID;
      n = NOT_VALID;
      Vgeff = d->vgst;
      dVgeff_dVg = 1.0;
      dVgeff_dVd = -dVth_dVd;
      dVgeff_dVb = -dVth_dVb;
      trace0("vgst>vghigh");
    }else{
      double Vof = s->vof0 + s->vofB * Vbs + s->vofD * Vds;
      n = s->n0 + s->nB / T1s + s->nD * Vds;
      double tmp = 0.5 / (n * m->Vtm);
      trace3("", Vof, n, tmp);
      
      double ExpArg1 = -Vds / m->Vtm;
      ExpArg1 = std::max(ExpArg1, -30.0);
      Exp1 = exp(ExpArg1);
      double tmp1 = 1.0 - Exp1;
      tmp1 = std::max(tmp1, 1.0e-18);
      double tmp2 = 2.0 * Aa * tmp1;
      trace4("", ExpArg1, Exp1, tmp1, tmp2);
      
      // exports Exp0, Vgeff, dVgeff_dVg, dVgeff_dVd, dVgeff_dVb
      if (d->vgst <= s->vglow) {
	double ExpArg = d->vgst * tmp;
	ExpArg = std::max(ExpArg, -30.0);
	Exp0 = exp(0.5 * Vof + ExpArg);
	Vgeff = sqrt(tmp2) * m->Vtm * Exp0;
	double T0 = n * m->Vtm;
	dVgeff_dVg = Vgeff * tmp;
	dVgeff_dVd = dVgeff_dVg * (n / tmp1 * Exp1 - dVth_dVd 
				   - d->vgst * s->nD / n + T0 * s->vofD);
	dVgeff_dVb = dVgeff_dVg * (s->vofB * T0 - dVth_dVb 
				 + s->nB * d->vgst / (n * T1s * T1s) * dT1s_dVb
				 + T0 * Inv_Aa * dAa_dVb);
	trace0("vgst<vglow");
      }else{
	double ExpArg = s->vglow * tmp;
	ExpArg = std::max(ExpArg, -30.0);
	Exp0 = exp(0.5 * Vof + ExpArg);
	Vgeff = sqrt(2.0 * Aa * (1.0 - Exp1)) * m->Vtm * Exp0;
	double Con1 = s->vghigh;
	double Con3 = Vgeff;
	double Con4 = Con3 * tmp;
	double SqrVghigh = s->vghigh * s->vghigh;
	double SqrVglow = s->vglow * s->vglow;
	double CubVghigh = s->vghigh * SqrVghigh;
	double CubVglow = s->vglow * SqrVglow;
	double T0 = 2.0 * s->vghigh;
	double T1 = 2.0 * s->vglow;
	double T2 = 3.0 * SqrVghigh;
	double T3 = 3.0 * SqrVglow;
	double T4 = s->vghigh - s->vglow;
	double T5 = SqrVghigh - SqrVglow;
	double T6 = CubVghigh - CubVglow;
	double T7 = Con1 - Con3;
	double delta = (T1-T0) * T6 + (T2-T3) * T5 + (T0*T3 - T1*T2) * T4;
	delta = 1.0 / delta;
	double Coeffb = (T1 - Con4 * T0) * T6 + (Con4 * T2 - T3) * T5 
	  + (T0 * T3 - T1 * T2) * T7;
	double Coeffc = (Con4-1.0) * T6 + (T2-T3) * T7 + (T3 - Con4*T2) * T4;
	double Coeffd = (T1-T0) * T7 + (1.0-Con4) * T5 + (Con4*T0 - T1) * T4;
	double Coeffa = SqrVghigh * (Coeffc + Coeffd * T0);
	Vgeff = (Coeffa + d->vgst * (Coeffb + d->vgst*(Coeffc+d->vgst*Coeffd)))
	  *delta;
	dVgeff_dVg = (Coeffb + d->vgst*(2.0*Coeffc+3.0*d->vgst*Coeffd)) *delta;
	T7 = Con3 * tmp;
	double T8 = dT1s_dVb * s->nB / (T1s * T1s * n);
	double T9 = n * m->Vtm;
	double dCon3_dVd = T7*(n*Exp1/tmp1 -s->vglow*s->nD/n + T9*s->vofD);
	double dCon3_dVb = T7*(T9*Inv_Aa*dAa_dVb + s->vglow*T8 + T9*s->vofB);
	double dCon4_dVd = tmp * dCon3_dVd - T7 * s->nD / n;
	double dCon4_dVb = tmp * dCon3_dVb + T7 * T8;
	
	double dCoeffb_dVd = dCon4_dVd*(T2*T5-T0*T6) + dCon3_dVd*(T1*T2-T0*T3);
	double dCoeffc_dVd = dCon4_dVd * (T6 - T2*T4) + dCon3_dVd * (T3 - T2);
	double dCoeffd_dVd = dCon4_dVd * (T0*T4 - T5) + dCon3_dVd * (T0 - T1);
	double dCoeffa_dVd = SqrVghigh * (dCoeffc_dVd + dCoeffd_dVd * T0);
	
	dVgeff_dVd = -dVgeff_dVg * dVth_dVd + (dCoeffa_dVd 
		+ d->vgst * (dCoeffb_dVd + d->vgst 
			    * (dCoeffc_dVd + d->vgst * dCoeffd_dVd))) * delta;
	
	double dCoeffb_dVb = dCon4_dVb*(T2*T5-T0*T6) + dCon3_dVb*(T1*T2-T0*T3);
	double dCoeffc_dVb = dCon4_dVb * (T6 - T2*T4) + dCon3_dVb * (T3 - T2);
	double dCoeffd_dVb = dCon4_dVb * (T0*T4 - T5) + dCon3_dVb * (T0 - T1);
	double dCoeffa_dVb = SqrVghigh * (dCoeffc_dVb + dCoeffd_dVb * T0);
	
	dVgeff_dVb = -dVgeff_dVg * dVth_dVb + (dCoeffa_dVb 
		+ d->vgst * (dCoeffb_dVb + d->vgst
			     * (dCoeffc_dVb + d->vgst * dCoeffd_dVb))) * delta;
	trace0("else");
      }
    }
    trace3("", Exp0, Exp1, n);
    trace4("", Vgeff, dVgeff_dVg, dVgeff_dVd, dVgeff_dVb);
    
    double dVdsat_dVd, dVdsat_dVg, dVdsat_dVb;
    if (Vgeff > 0.0) {	// normal operation
      d->cutoff = false;
      double Uvert = 1.0 + Vgeff * (Ua + Vgeff * Ub);
      Uvert = std::max(Uvert, 0.2);
      double Inv_Uvert = 1.0 / Uvert;
      double dUvert_dVg, dUvert_dVd, dUvert_dVb;
      {
	double T8 = Ua + 2.0 * Ub * Vgeff;
	dUvert_dVg = T8 * dVgeff_dVg;
	dUvert_dVd = T8 * dVgeff_dVd;
	dUvert_dVb = T8 * dVgeff_dVb + Vgeff * (s->uaB + Vgeff * s->ubB);
	trace2("", T8, Uvert);
	trace3("", dUvert_dVg, dUvert_dVd, dUvert_dVb);
      }
      
      double Vc, dVc_dVg, dVc_dVd, dVc_dVb;
      {
	double T8 = U1s * Inv_Aa * Inv_Uvert;
	Vc = T8 * Vgeff;
	double T9 = Vc * Inv_Uvert;
	dVc_dVg = T8 * dVgeff_dVg - T9 * dUvert_dVg;
	dVc_dVd = T8 * dVgeff_dVd - T9 * dUvert_dVd;
	dVc_dVb = T8 * dVgeff_dVb 
	  + s->u1B * Vgeff * Inv_Aa * Inv_Uvert
	  - Vc * Inv_Aa * dAa_dVb
	  - T9 * dUvert_dVb;
	trace3("", T8, T9, Vc);
	trace3("", dVc_dVg, dVc_dVd, dVc_dVb);
      }
      
      double Kk, dKk_dVc;
      {
	double tmp2 = sqrt(1.0 + 2.0 * Vc);
	Kk = 0.5 * (1.0 + Vc + tmp2);
	dKk_dVc = 0.5  + 0.5 / tmp2;
	trace3("", tmp2, Kk, dKk_dVc);
      }
      
      {
	double T8 = Inv_Aa / sqrt(Kk);
	d->vdsat = std::max(Vgeff * T8, 1.0e-18);
	double T9 = 0.5 * d->vdsat * dKk_dVc / Kk;
	dVdsat_dVd = T8 * dVgeff_dVd - T9 * dVc_dVd;
	dVdsat_dVg = T8 * dVgeff_dVg - T9 * dVc_dVg;
	dVdsat_dVb = T8 * dVgeff_dVb - T9 * dVc_dVb - d->vdsat*Inv_Aa*dAa_dVb;
	trace3("", T8, T9, d->vdsat);
	trace3("", dVdsat_dVd, dVdsat_dVg, dVdsat_dVb);
      }
      
      double Beta, dBeta_dVd, dBeta_dVg, dBeta_dVb;
      {
	double Beta0 = s->beta0  + s->beta0B * Vbs;
	double Betas = s->betas0 + s->betasB * Vbs;
	double Beta2 = s->beta20 + s->beta2B * Vbs + s->beta2G * Vgs;
	double Beta3 = s->beta30 + s->beta3B * Vbs + s->beta3G * Vgs;
	double Beta4 = s->beta40 + s->beta4B * Vbs + s->beta4G * Vgs;
	double Beta1 = Betas - (Beta0 + m->vdd * (Beta3 - m->vdd * Beta4));
	trace4("", Beta0, s->beta0, s->beta0B, Vbs);
	trace4("", Betas, s->betas0, s->betasB, Vgs);
	trace4("", Beta2, s->beta20, s->beta2B, s->beta2G);
	trace4("", Beta3, s->beta30, s->beta3B, s->beta3G);
	trace4("", Beta4, s->beta40, s->beta4B, s->beta4G);
	trace2("", Beta1, m->vdd);
	
	double T0 = Vds * Beta2 / d->vdsat;
	T0 = std::min(T0, 30.0);
	double T1 = exp(T0);
	double T2 = T1 * T1;
	double T3 = T2 + 1.0;
	trace4("", T0, T1, T2, T3);
	double tanh = (T2 - 1.0) / T3;
	double Sqrsech = 4.0 * T2 / (T3 * T3);
	trace2("", tanh, Sqrsech);
	
	Beta = Beta0 + Beta1 * tanh + Vds * (Beta3 - Beta4 * Vds);
	double T4 = Beta1 * Sqrsech / d->vdsat;
	double T5 = m->vdd * tanh;
	dBeta_dVd = Beta3 - 2.0*Beta4*Vds + T4*(Beta2-T0*dVdsat_dVd);
	dBeta_dVg = T4 * (s->beta2G * Vds - T0 * dVdsat_dVg)
	  + s->beta3G * (Vds - T5) 
	  - s->beta4G * (Vds * Vds - m->vdd * T5);
	double dBeta1_dVb = s->Arg;
	dBeta_dVb = s->beta0B
	  + dBeta1_dVb * tanh
	  + Vds * (s->beta3B - Vds * s->beta4B)
	  + T4 * (s->beta2B * Vds - T0 * dVdsat_dVb);
	trace3("", T4, T5, dBeta1_dVb);
	trace4("", Beta, dBeta_dVd, dBeta_dVg, dBeta_dVb);
      }
      
      if (d->vgst > s->vglow) {	// not subthreshold
	d->subthreshold = false;
	if (Vds <= d->vdsat) {		// triode region
	  d->saturated = false;
	  double T3 = Vds / d->vdsat;
	  double T4 = T3 - 1.0;
	  double T2 =  1.0 - s->u1D * T4 * T4;
	  double U1 =  U1s * T2;
	  double Utot = Uvert + U1 * Vds;
	  Utot = std::max(Utot, 0.5);
	  double Inv_Utot = 1.0 / Utot;
	  double T5 = 2.0 * U1s * s->u1D * T4 / d->vdsat;
	  double dU1_dVd = T5 * (T3 * dVdsat_dVd - 1.0);
	  double dU1_dVg = T5 * T3 * dVdsat_dVg;
	  double dU1_dVb = T5 * T3 * dVdsat_dVb + s->u1B * T2;
	  double dUtot_dVd = dUvert_dVd + U1 + Vds * dU1_dVd;
	  double dUtot_dVg = dUvert_dVg + Vds * dU1_dVg;
	  double dUtot_dVb = dUvert_dVb + Vds * dU1_dVb;
	  
	  double tmp1 = (Vgeff - 0.5 * Aa * Vds);
	  double tmp3 = tmp1 * Vds;
	  double Betaeff = Beta * Inv_Utot;
	  d->ids = Betaeff * tmp3;
	  double T6 = d->ids / Betaeff * Inv_Utot;
	  d->gds = T6 * (dBeta_dVd - Betaeff * dUtot_dVd)
	    + Betaeff * (tmp1 + (dVgeff_dVd - 0.5 * Aa) * Vds);
	  d->gmf = T6 * (dBeta_dVg - Betaeff * dUtot_dVg)
	    + Betaeff * Vds * dVgeff_dVg;
	  d->gmbf = T6 * (dBeta_dVb - Betaeff * dUtot_dVb)
	    + Betaeff * Vds * (dVgeff_dVb - 0.5 * Vds * dAa_dVb);
	}else{	// Saturation
	  d->saturated = true;
	  double Inv_Kk = 1.0 / Kk;
	  double tmp1 = Vgeff * Inv_Aa * Inv_Kk;
	  double tmp3 = 0.5 * Vgeff * tmp1;
	  double Betaeff = Beta * Inv_Uvert;
	  d->ids = Betaeff * tmp3;
	  double T0 = d->ids / Betaeff * Inv_Uvert;
	  double T1 = Betaeff * Vgeff * Inv_Aa * Inv_Kk;
	  double T2 = d->ids * Inv_Kk * dKk_dVc;
	  
	  if (s->ai0 != 0.0) {
	    double Ai = s->ai0 + s->aiB * Vbs;
	    double Bi = s->bi0 + s->biB * Vbs;
	    double T5 = Bi / (Vds - d->vdsat);
	    T5 = std::min(T5, 30.0);
	    double T6 = exp(-T5);
	    double FR = 1.0 + Ai * T6;
	    double T7 = T5 / (Vds - d->vdsat);
	    double T8 = (1.0 - FR) * T7;
	    double dFR_dVd = T8 * (dVdsat_dVd - 1.0);
	    double dFR_dVg = T8 * dVdsat_dVg;
	    double dFR_dVb = T8 * dVdsat_dVb 
	      + T6 * (s->aiB - Ai * s->biB / (Vds - d->vdsat));
	    
	    d->gds = (T0 * (dBeta_dVd - Betaeff * dUvert_dVd) 
		     + T1 * dVgeff_dVd - T2 * dVc_dVd) * FR + d->ids * dFR_dVd;
	    d->gmf = (T0 * (dBeta_dVg - Betaeff * dUvert_dVg) 
		     + T1 * dVgeff_dVg - T2 * dVc_dVg) * FR + d->ids * dFR_dVg;
	    d->gmbf = (T0 * (dBeta_dVb - Betaeff * dUvert_dVb)
		      + T1 * dVgeff_dVb - T2 * dVc_dVb 
		      - d->ids * Inv_Aa * dAa_dVb) * FR + d->ids * dFR_dVb;
	    d->ids *= FR;
	  }else{
	    d->gds = T0 * (dBeta_dVd - Betaeff * dUvert_dVd)
	      + T1 * dVgeff_dVd - T2 * dVc_dVd;
	    d->gmf = T0 * (dBeta_dVg - Betaeff * dUvert_dVg)
	      + T1 * dVgeff_dVg - T2 * dVc_dVg;
	    d->gmbf = T0 * (dBeta_dVb - Betaeff * dUvert_dVb)
	      + T1 * dVgeff_dVb - T2 * dVc_dVb - d->ids * Inv_Aa * dAa_dVb;
	  }
	}
      }else{	// subthreshold
	d->subthreshold = true;
	assert(Exp0 != NOT_VALID);
	double T0 = Exp0 * Exp0;
	assert(Exp1 != NOT_VALID);
	double T1 = Exp1;
	trace4("sub", Exp0, Exp1, T0, T1);
	trace2("", n, m->Vtm);
	d->ids = Beta * m->Vtm * m->Vtm * T0 * (1.0 - T1);
	double T2 = d->ids / Beta;
	double T4 = n * m->Vtm;
	double T3 = d->ids / T4;
	trace4("", d->ids, T2, T4, T3);
	double FR, dFR_dVd, dFR_dVg, dFR_dVb;
	if ((Vds > d->vdsat) && s->ai0 != 0.0) {
	  d->saturated = true;
	  double Ai = s->ai0 + s->aiB * Vbs;
	  double Bi = s->bi0 + s->biB * Vbs;
	  double T5 = Bi / (Vds - d->vdsat);
	  trace3("", Ai, Bi, T5);
	  T5 = std::min(T5, 30.0);
	  double T6 = exp(-T5);
	  FR = 1.0 + Ai * T6;
	  double T7 = T5 / (Vds - d->vdsat);
	  double T8 = (1.0 - FR) * T7;
	  trace4("", T5, T6, T7, T8);
	  dFR_dVd = T8 * (dVdsat_dVd - 1.0);
	  dFR_dVg = T8 * dVdsat_dVg;
	  dFR_dVb = T8 * dVdsat_dVb + T6 * (s->aiB-Ai*s->biB/(Vds-d->vdsat));
	  trace4("ai0!=0", FR, dFR_dVd, dFR_dVg, dFR_dVb);
	}else{
	  d->saturated = false;
	  FR = 1.0;
	  dFR_dVd = 0.0;
	  dFR_dVg = 0.0;
	  dFR_dVb = 0.0;
	  trace4("ai0==0", FR, dFR_dVd, dFR_dVg, dFR_dVb);
	}
	
	d->gds = (T2 * dBeta_dVd 
		  + T3 * (s->vofD * T4 - dVth_dVd - s->nD * d->vgst / n)
		  + Beta * m->Vtm * T0 * T1) * FR + d->ids * dFR_dVd;
	d->gmf = (T2 * dBeta_dVg + T3) * FR + d->ids * dFR_dVg;
	d->gmbf = (T2 * dBeta_dVb + T3 * (s->vofB * T4 - dVth_dVb + s->nB
		* d->vgst / (n * T1s * T1s) * dT1s_dVb)) * FR + d->ids*dFR_dVb;
	d->ids *= FR;
      }
    }else{	// cutoff???
      d->cutoff = true;
      // reachable only if vghigh and vgst both negative
      d->vdsat = 0.0;
      dVdsat_dVd = dVdsat_dVg = dVdsat_dVb = 0.0;
      d->ids = 0.0;
      d->gmf  = 0.0;
      d->gds = 0.0;
      d->gmbf = 0.0;
    }
    trace4("", d->vdsat, dVdsat_dVd, dVdsat_dVg, dVdsat_dVb);
    trace4("", d->ids, d->gmf, d->gds, d->gmbf);
    
    /* Some Limiting of DC Parameters */
    d->gds = std::max(d->gds, 1.0e-20);
    d->ids = std::max(d->ids, 1.0e-50);
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    double Vbseff, dVbseff_dVb;
    if (Vbs < 0.0) {
      Vbseff = Vbs;
      dVbseff_dVb = 1.0;
    }else{
      Vbseff = s->phi - Phisb;
      dVbseff_dVb = -dPhisb_dVb;
    }
    trace3("", Vbs, Vbseff, dVbseff_dVb);
    
    double Arg1 = Vgs - Vbseff - s->vfb;
    double Arg2 = Arg1 - d->vgst;
    trace2("", Arg1, Arg2);
    double Qbulk = s->One_Third_CoxWL * Arg2;
    double dQbulk_dVb = s->One_Third_CoxWL * (dVth_dVb - dVbseff_dVb);
    double dQbulk_dVd = s->One_Third_CoxWL * dVth_dVd;
    trace3("", Qbulk, dQbulk_dVb, dQbulk_dVd);
    if (Arg1 <= 0.0) { // accumulation region
      d->qgate = s->cgate * Arg1;
      d->qbulk = -(d->qgate);
      d->qdrn = 0.0;
      
      d->cggb = s->cgate;
      d->cgdb = 0.0;
      d->cgsb = -d->cggb * (1.0 - dVbseff_dVb);
      
      d->cdgb = 0.0;
      d->cddb = 0.0;
      d->cdsb = 0.0;
      
      d->cbgb = -s->cgate;
      d->cbdb = 0.0;
      d->cbsb = -d->cgsb;
      trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
      trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
      trace4("acc", d->qdrn, d->cdgb, d->cddb, d->cdsb);
    }else if (d->vgst <= 0.0) { // subthreshold
      double T2 = Arg1 / Arg2;
      double T3 = T2 * T2 * (s->cgate - s->Two_Third_CoxWL * T2);
      
      d->qgate = s->cgate * Arg1 * (1.0 - T2 * (1.0 - T2 / 3.0));
      d->qbulk = -(d->qgate);
      d->qdrn = 0.0;
      
      d->cggb = s->cgate * (1.0 - T2 * (2.0 - T2));
      d->cgdb = T3 * dVth_dVd;
      double tmp = T3 * dVth_dVb - (d->cggb + T3) * dVbseff_dVb;
      d->cgsb = -(d->cggb + d->cgdb + tmp);
      
      d->cbgb = -d->cggb;
      d->cbdb = -d->cgdb;
      d->cbsb = -d->cgsb;
      
      d->cdgb = 0.0;
      d->cddb = 0.0;
      d->cdsb = 0.0;
      trace3("", T2, T3, tmp);
      trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
      trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
      trace4("sub", d->qdrn, d->cdgb, d->cddb, d->cdsb);
    }else{
      double Vdsat; // changes dVdsat_dVd, dVdsat_dVg, dVdsat_dVb;
      if (d->vgst < s->vghigh) {
	double Uvert = 1.0 + d->vgst * (Ua + d->vgst * Ub);
	Uvert = std::max(Uvert, 0.2);
	double Inv_Uvert = 1.0 / Uvert;
	double dUvert_dVg = Ua + 2.0 * Ub * d->vgst;
	double dUvert_dVd = -dUvert_dVg * dVth_dVd;
	double dUvert_dVb = -dUvert_dVg * dVth_dVb 
	  + d->vgst * (s->uaB + d->vgst * s->ubB);
	trace2("", Uvert, Inv_Uvert);
	trace3("", dUvert_dVg, dUvert_dVd, dUvert_dVb);
	
	double T8 = U1s * Inv_Aa * Inv_Uvert;
	double Vc = T8 * d->vgst;
	double T9 = Vc * Inv_Uvert;
	double dVc_dVg = T8 - T9 * dUvert_dVg;
	double dVc_dVd = -T8 * dVth_dVd - T9 * dUvert_dVd;
	double dVc_dVb = -T8 * dVth_dVb
	  + s->u1B * d->vgst * Inv_Aa * Inv_Uvert 
	  - Vc * Inv_Aa * dAa_dVb - T9 * dUvert_dVb;
	trace3("", T8, T9, Vc);
	trace3("", dVc_dVg, dVc_dVd, dVc_dVb);
	
	double tmp2 = sqrt(1.0 + 2.0 * Vc);
	double Kk = 0.5 * (1.0 + Vc + tmp2);
	double dKk_dVc = 0.5  + 0.5 / tmp2;
	trace3("", tmp2, Kk, dKk_dVc);
	
	T8 = Inv_Aa / sqrt(Kk);
	Vdsat = d->vgst * T8;
	T9 = 0.5 * Vdsat * dKk_dVc / Kk;
	trace2("", T8, T9);
	dVdsat_dVd = -T8 * dVth_dVd - T9 * dVc_dVd;
	dVdsat_dVg = T8 - T9 * dVc_dVg;
	dVdsat_dVb = -T8*dVth_dVb - T9*dVc_dVb - Vdsat*Inv_Aa*dAa_dVb;
	trace2("new", d->vdsat, Vdsat);
	trace3("", dVdsat_dVd, dVdsat_dVg, dVdsat_dVb);
      }else{
	Vdsat = d->vdsat;
	trace2("keep", d->vdsat, Vdsat);
	trace3("", dVdsat_dVd, dVdsat_dVg, dVdsat_dVb);
	// keep dVdsat_dVd, dVdsat_dVg, dVdsat_dVb;
      }
      if (Vds >= Vdsat) {       /* saturation region */
	d->cggb = s->Two_Third_CoxWL;
	d->cgdb = -d->cggb * dVth_dVd + dQbulk_dVd;
	double tmp = -d->cggb * dVth_dVb + dQbulk_dVb;
	d->cgsb = -(d->cggb + d->cgdb + tmp);
	trace1("", tmp);
	
	d->cbgb = 0.0;
	d->cbdb = -dQbulk_dVd;
	d->cbsb = dQbulk_dVd + dQbulk_dVb;
	
	d->cdgb = -0.4 * d->cggb;
	d->cddb = -d->cdgb * dVth_dVd;
	tmp = -d->cdgb * dVth_dVb;
	d->cdsb = -(d->cdgb + d->cddb + tmp);
	trace1("", tmp);
	
	d->qbulk = -Qbulk;
	d->qgate = s->Two_Third_CoxWL * d->vgst + Qbulk;
	d->qdrn = d->cdgb * d->vgst;
	trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
	trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
	trace4("sat", d->qdrn, d->cdgb, d->cddb, d->cdsb);
      }else{       /* linear region  */
	double T7 = Vds / Vdsat;
	double T8 = d->vgst / Vdsat;
	double T6 = T7 * T8;
	double T9 = 1.0 - T7;
	double Vgdt = d->vgst * T9;
	double T0 = d->vgst / (d->vgst + Vgdt);
	double T1 = Vgdt / (d->vgst + Vgdt);
	double T5 = T0 * T1;
	double T2 = 1.0 - T1 + T5;
	double T3 = 1.0 - T0 + T5;
	trace4("", T7, T8, T6, T9);
	trace2("", Vgdt, T0);
	trace4("", T1, T5, T2, T3);
	
	double dVgdt_dVg = T9 + T6 * dVdsat_dVg;
	double dVgdt_dVd = T6 * dVdsat_dVd - T8 -T9 * dVth_dVd;
	double dVgdt_dVb = T6 * dVdsat_dVb -T9 * dVth_dVb;
	trace3("", dVgdt_dVg, dVgdt_dVd, dVgdt_dVb);
	
	d->qgate = s->Two_Third_CoxWL * (d->vgst + Vgdt 
				   - Vgdt * T0) + Qbulk;
	d->qbulk = -Qbulk;
	d->qdrn = -s->One_Third_CoxWL * (0.2 * Vgdt 
				    + 0.8 * d->vgst + Vgdt * T1 
				    + 0.2 * T5 * (Vgdt - d->vgst));
	
	d->cggb = s->Two_Third_CoxWL * (T2 + T3 * dVgdt_dVg);
	d->cgdb = s->Two_Third_CoxWL * (T3*dVgdt_dVd-T2*dVth_dVd) + dQbulk_dVd;
	double tmp = dQbulk_dVb +s->Two_Third_CoxWL*(T3*dVgdt_dVb-T2*dVth_dVb);
	d->cgsb = -(d->cggb + d->cgdb + tmp);
	trace1("", tmp);
	
	T2 = 0.8 - 0.4 * T1 * (2.0 * T1 + T0 + T0 * (T1 - T0));
	T3 = 0.2 + T1 + T0 * (1.0 - 0.4 * T0 * (T1 + 3.0 * T0));
	d->cdgb = -s->One_Third_CoxWL * (T2 + T3 * dVgdt_dVg);
	d->cddb = s->One_Third_CoxWL * (T2 * dVth_dVd - T3 * dVgdt_dVd);
	tmp = s->One_Third_CoxWL * (T2 * dVth_dVb - T3 * dVgdt_dVb);
	d->cdsb = -(d->cdgb + tmp + d->cddb);
	trace3("", T2, T3, tmp);
	
	d->cbgb = 0.0;
	d->cbdb = -dQbulk_dVd;
	d->cbsb = dQbulk_dVd + dQbulk_dVb;
	trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
	trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
	trace4("lin", d->qdrn, d->cdgb, d->cddb, d->cdsb);
      }
    }
    if (d->reversed) {
      d->ids *= -1;
      d->gmr = d->gmf;
      d->gmbr = d->gmbf;
      d->gmf = d->gmbf = 0;
    }else{
      d->gmr = d->gmbr = 0.;
    }
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
