/* $Id: d_mos4.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.
 *------------------------------------------------------------------
 * MOS BSIM1 model.
 * derived from Spice3f4,Copyright 1990 Regents of the University of California
 * 1985 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_mos4.h"
/*--------------------------------------------------------------------------*/
const double NA(NOT_INPUT);
const double INF(BIGBIG);
/*--------------------------------------------------------------------------*/
int MODEL_BUILT_IN_MOS4::_count = 0;
/*--------------------------------------------------------------------------*/
const int LEVEL(4);
/*--------------------------------------------------------------------------*/
namespace MODEL_BUILT_IN_MOS4_DISPATCHER { 
  static DEV_BUILT_IN_MOS p1d;
  static MODEL_BUILT_IN_MOS4 p1(&p1d);
  static DISPATCHER<MODEL_CARD>::INSTALL
    d1(&model_dispatcher, "nmos4|pmos4", &p1);
}
/*--------------------------------------------------------------------------*/
void SDP_BUILT_IN_MOS4::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_MOS4* m = prechecked_cast<const MODEL_BUILT_IN_MOS4*>(c->model());
  assert(m);
  const CARD_LIST* par_scope = m->scope();
  assert(par_scope);

      l_eff -= m->dl;
      w_eff -= m->dw;
      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);
    //phi = std::max(phi, .1);
  vfb = m->vfb(L, W, 0., par_scope);
  k1 = m->k1(L, W, 0., par_scope);
  k2 = m->k2(L, W, 0., par_scope);
  eta = m->eta(L, W, 0., par_scope);
  etaB = m->etaB(L, W, 0., par_scope);
  etaD = m->etaD(L, W, 0., par_scope);
  mobZero = m->mobZero(L, W, 0., par_scope);
  mobZeroB = m->mobZeroB(L, W, 0., par_scope);
  mobVdd = m->mobVdd(L, W, 0., par_scope);
  mobVddB = m->mobVddB(L, W, 0., par_scope);
  mobVddD = m->mobVddD(L, W, 0., par_scope);
  ugs = m->ugs(L, W, 0., par_scope);
  ugsB = m->ugsB(L, W, 0., par_scope);
  uds = m->uds(L, W, 0., par_scope);
  udsB = m->udsB(L, W, 0., par_scope);
  udsD = m->udsD(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);
  // adjust: calculated
    betaZero = mobZero  * CoxWoverL;
    betaZeroB = mobZeroB * CoxWoverL;
    betaVdd = mobVdd   * CoxWoverL;
    betaVddB = mobVddB  * CoxWoverL;
    betaVddD = mobVddD  * CoxWoverL;
    vt0 = vfb + phi + k1 * sqrt(phi) - k2 * phi;
  // code_post
}
/*--------------------------------------------------------------------------*/
TDP_BUILT_IN_MOS4::TDP_BUILT_IN_MOS4(const DEV_BUILT_IN_MOS* d)
  :TDP_BUILT_IN_MOS_BASE(d)
{
}
/*--------------------------------------------------------------------------*/
MODEL_BUILT_IN_MOS4::MODEL_BUILT_IN_MOS4(const BASE_SUBCKT* p)
  :MODEL_BUILT_IN_MOS_BASE(p),
   phi(0.),
   vfb(0.),
   k1(0.),
   k2(0.),
   eta(0.),
   etaB(0.),
   etaD(0.),
   mobZero(0.),
   mobZeroB(0.),
   mobVdd(0.),
   mobVddB(0.),
   mobVddD(0.),
   ugs(0.),
   ugsB(0.),
   uds(0.),
   udsB(0.),
   udsD(0.),
   n0(0.),
   nB(0.),
   nD(0.),
   dl_u(0.),
   dw_u(0.),
   tox_u(0.),
   vdd(0.),
   wdf(0.),
   dell(0.),
   temp(300.15),
   xpart(0.),
   dl(NA),
   dw(NA),
   tox(NA),
   cox(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_MOS4::MODEL_BUILT_IN_MOS4(const MODEL_BUILT_IN_MOS4& p)
  :MODEL_BUILT_IN_MOS_BASE(p),
   phi(p.phi),
   vfb(p.vfb),
   k1(p.k1),
   k2(p.k2),
   eta(p.eta),
   etaB(p.etaB),
   etaD(p.etaD),
   mobZero(p.mobZero),
   mobZeroB(p.mobZeroB),
   mobVdd(p.mobVdd),
   mobVddB(p.mobVddB),
   mobVddD(p.mobVddD),
   ugs(p.ugs),
   ugsB(p.ugsB),
   uds(p.uds),
   udsB(p.udsB),
   udsD(p.udsD),
   n0(p.n0),
   nB(p.nB),
   nD(p.nD),
   dl_u(p.dl_u),
   dw_u(p.dw_u),
   tox_u(p.tox_u),
   vdd(p.vdd),
   wdf(p.wdf),
   dell(p.dell),
   temp(p.temp),
   xpart(p.xpart),
   dl(p.dl),
   dw(p.dw),
   tox(p.tox),
   cox(p.cox)
{
  if (ENV::run_mode != rPRE_MAIN) {
    ++_count;
  }else{untested();//194
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS4::dev_type()const
{
  if (polarity == pN) {
    return "nmos4";
  }else if (polarity == pP) {
    return "pmos4";
  }else{untested();//235
    return MODEL_BUILT_IN_MOS_BASE::dev_type();
  }
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS4::set_dev_type(const std::string& new_type)
{
  if (Umatch(new_type, "nmos4 ")) {
    polarity = pN;
  }else if (Umatch(new_type, "pmos4 ")) {
    polarity = pP;
  }else{
    MODEL_BUILT_IN_MOS_BASE::set_dev_type(new_type);
  }
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS4::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->wdf), 0., par_scope);
    e_val(&(this->dell), 0., par_scope);
    e_val(&(this->temp), 300.15, 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->wdf), 0., par_scope);
    e_val(&(this->dell), 0., par_scope);
    e_val(&(this->temp), 300.15, 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;
    // final adjust: post
    // final adjust: done
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS4::precalc_last()
{
    MODEL_BUILT_IN_MOS_BASE::precalc_last();
}
/*--------------------------------------------------------------------------*/
SDP_CARD* MODEL_BUILT_IN_MOS4::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_MOS4(c);
    }
  }else{
    return MODEL_BUILT_IN_MOS_BASE::new_sdp(c);
  }
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS4::set_param_by_index(int i, std::string& value, int offset)
{
  switch (MODEL_BUILT_IN_MOS4::param_count() - 1 - i) {
  case 0: level = value; break; //4
  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: eta.set_nom(value); break;
  case 24: eta.set_w(value); break;
  case 25: eta.set_l(value); break;
  case 26: eta.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: etaD.set_nom(value); break;
  case 32: etaD.set_w(value); break;
  case 33: etaD.set_l(value); break;
  case 34: etaD.set_p(value); break;
  case 35: mobZero.set_nom(value); break;
  case 36: mobZero.set_w(value); break;
  case 37: mobZero.set_l(value); break;
  case 38: mobZero.set_p(value); break;
  case 39: mobZeroB.set_nom(value); break;
  case 40: mobZeroB.set_w(value); break;
  case 41: mobZeroB.set_l(value); break;
  case 42: mobZeroB.set_p(value); break;
  case 43: mobVdd.set_nom(value); break;
  case 44: mobVdd.set_w(value); break;
  case 45: mobVdd.set_l(value); break;
  case 46: mobVdd.set_p(value); break;
  case 47: mobVddB.set_nom(value); break;
  case 48: mobVddB.set_w(value); break;
  case 49: mobVddB.set_l(value); break;
  case 50: mobVddB.set_p(value); break;
  case 51: mobVddD.set_nom(value); break;
  case 52: mobVddD.set_w(value); break;
  case 53: mobVddD.set_l(value); break;
  case 54: mobVddD.set_p(value); break;
  case 55: ugs.set_nom(value); break;
  case 56: ugs.set_w(value); break;
  case 57: ugs.set_l(value); break;
  case 58: ugs.set_p(value); break;
  case 59: ugsB.set_nom(value); break;
  case 60: ugsB.set_w(value); break;
  case 61: ugsB.set_l(value); break;
  case 62: ugsB.set_p(value); break;
  case 63: uds.set_nom(value); break;
  case 64: uds.set_w(value); break;
  case 65: uds.set_l(value); break;
  case 66: uds.set_p(value); break;
  case 67: udsB.set_nom(value); break;
  case 68: udsB.set_w(value); break;
  case 69: udsB.set_l(value); break;
  case 70: udsB.set_p(value); break;
  case 71: udsD.set_nom(value); break;
  case 72: udsD.set_w(value); break;
  case 73: udsD.set_l(value); break;
  case 74: udsD.set_p(value); break;
  case 75: n0.set_nom(value); break;
  case 76: n0.set_w(value); break;
  case 77: n0.set_l(value); break;
  case 78: n0.set_p(value); break;
  case 79: nB.set_nom(value); break;
  case 80: nB.set_w(value); break;
  case 81: nB.set_l(value); break;
  case 82: nB.set_p(value); break;
  case 83: nD.set_nom(value); break;
  case 84: nD.set_w(value); break;
  case 85: nD.set_l(value); break;
  case 86: nD.set_p(value); break;
  case 87: dl_u = value; break;
  case 88: dw_u = value; break;
  case 89: tox_u = value; break;
  case 90: vdd = value; break;
  case 91: wdf = value; break;
  case 92: dell = value; break;
  case 93: temp = value; break;
  case 94: xpart = value; break;
  default: MODEL_BUILT_IN_MOS_BASE::set_param_by_index(i, value, offset); break;
  }
}
/*--------------------------------------------------------------------------*/
bool MODEL_BUILT_IN_MOS4::param_is_printable(int i)const
{
  switch (MODEL_BUILT_IN_MOS4::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 (eta.w_has_value());
  case 25:  return (eta.l_has_value());
  case 26:  return (eta.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 (etaD.w_has_value());
  case 33:  return (etaD.l_has_value());
  case 34:  return (etaD.p_has_value());
  case 35:  return (true);
  case 36:  return (mobZero.w_has_value());
  case 37:  return (mobZero.l_has_value());
  case 38:  return (mobZero.p_has_value());
  case 39:  return (true);
  case 40:  return (mobZeroB.w_has_value());
  case 41:  return (mobZeroB.l_has_value());
  case 42:  return (mobZeroB.p_has_value());
  case 43:  return (true);
  case 44:  return (mobVdd.w_has_value());
  case 45:  return (mobVdd.l_has_value());
  case 46:  return (mobVdd.p_has_value());
  case 47:  return (true);
  case 48:  return (mobVddB.w_has_value());
  case 49:  return (mobVddB.l_has_value());
  case 50:  return (mobVddB.p_has_value());
  case 51:  return (true);
  case 52:  return (mobVddD.w_has_value());
  case 53:  return (mobVddD.l_has_value());
  case 54:  return (mobVddD.p_has_value());
  case 55:  return (true);
  case 56:  return (ugs.w_has_value());
  case 57:  return (ugs.l_has_value());
  case 58:  return (ugs.p_has_value());
  case 59:  return (true);
  case 60:  return (ugsB.w_has_value());
  case 61:  return (ugsB.l_has_value());
  case 62:  return (ugsB.p_has_value());
  case 63:  return (true);
  case 64:  return (uds.w_has_value());
  case 65:  return (uds.l_has_value());
  case 66:  return (uds.p_has_value());
  case 67:  return (true);
  case 68:  return (udsB.w_has_value());
  case 69:  return (udsB.l_has_value());
  case 70:  return (udsB.p_has_value());
  case 71:  return (true);
  case 72:  return (udsD.w_has_value());
  case 73:  return (udsD.l_has_value());
  case 74:  return (udsD.p_has_value());
  case 75:  return (true);
  case 76:  return (n0.w_has_value());
  case 77:  return (n0.l_has_value());
  case 78:  return (n0.p_has_value());
  case 79:  return (true);
  case 80:  return (nB.w_has_value());
  case 81:  return (nB.l_has_value());
  case 82:  return (nB.p_has_value());
  case 83:  return (true);
  case 84:  return (nD.w_has_value());
  case 85:  return (nD.l_has_value());
  case 86:  return (nD.p_has_value());
  case 87:  return (true);
  case 88:  return (true);
  case 89:  return (true);
  case 90:  return (true);
  case 91:  return (true);
  case 92:  return (true);
  case 93:  return (true);
  case 94:  return (true);
  default: return MODEL_BUILT_IN_MOS_BASE::param_is_printable(i);
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS4::param_name(int i)const
{
  switch (MODEL_BUILT_IN_MOS4::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 "eta";
  case 24:  return "weta";
  case 25:  return "leta";
  case 26:  return "peta";
  case 27:  return "x2e";
  case 28:  return "wx2e";
  case 29:  return "lx2e";
  case 30:  return "px2e";
  case 31:  return "x3e";
  case 32:  return "wx3e";
  case 33:  return "lx3e";
  case 34:  return "px3e";
  case 35:  return "muz";
  case 36:  return "wmuz";
  case 37:  return "lmuz";
  case 38:  return "pmuz";
  case 39:  return "x2mz";
  case 40:  return "wx2mz";
  case 41:  return "lx2mz";
  case 42:  return "px2mz";
  case 43:  return "mus";
  case 44:  return "wmus";
  case 45:  return "lmus";
  case 46:  return "pmus";
  case 47:  return "x2ms";
  case 48:  return "wx2ms";
  case 49:  return "lx2ms";
  case 50:  return "px2ms";
  case 51:  return "x3ms";
  case 52:  return "wx3ms";
  case 53:  return "lx3ms";
  case 54:  return "px3ms";
  case 55:  return "u0";
  case 56:  return "wu0";
  case 57:  return "lu0";
  case 58:  return "pu0";
  case 59:  return "x2u0";
  case 60:  return "wx2u0";
  case 61:  return "lx2u0";
  case 62:  return "px2u0";
  case 63:  return "u1";
  case 64:  return "wu1";
  case 65:  return "lu1";
  case 66:  return "pu1";
  case 67:  return "x2u1";
  case 68:  return "wx2u1";
  case 69:  return "lx2u1";
  case 70:  return "px2u1";
  case 71:  return "x3u1";
  case 72:  return "wx3u1";
  case 73:  return "lx3u1";
  case 74:  return "px3u1";
  case 75:  return "n0";
  case 76:  return "wn0";
  case 77:  return "ln0";
  case 78:  return "pn0";
  case 79:  return "nb";
  case 80:  return "wnb";
  case 81:  return "lnb";
  case 82:  return "pnb";
  case 83:  return "nd";
  case 84:  return "wnd";
  case 85:  return "lnd";
  case 86:  return "pnd";
  case 87:  return "dl";
  case 88:  return "dw";
  case 89:  return "tox";
  case 90:  return "vdd";
  case 91:  return "wdf";
  case 92:  return "dell";
  case 93:  return "temp";
  case 94:  return "xpart";
  default: return MODEL_BUILT_IN_MOS_BASE::param_name(i);
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS4::param_name(int i, int j)const
{
  if (j == 0) {
    return param_name(i);
  }else if (j == 1) {
    switch (MODEL_BUILT_IN_MOS4::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 "";
    default: return MODEL_BUILT_IN_MOS_BASE::param_name(i, j);
    }
  }else if (i < 95) {
    return "";
  }else{
    return MODEL_BUILT_IN_MOS_BASE::param_name(i, j);
  }
}
/*--------------------------------------------------------------------------*/
std::string MODEL_BUILT_IN_MOS4::param_value(int i)const
{
  switch (MODEL_BUILT_IN_MOS4::param_count() - 1 - i) {
  case 0:  return "4";
  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 eta.string();
  case 24:  return eta.w_string();
  case 25:  return eta.l_string();
  case 26:  return eta.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 etaD.string();
  case 32:  return etaD.w_string();
  case 33:  return etaD.l_string();
  case 34:  return etaD.p_string();
  case 35:  return mobZero.string();
  case 36:  return mobZero.w_string();
  case 37:  return mobZero.l_string();
  case 38:  return mobZero.p_string();
  case 39:  return mobZeroB.string();
  case 40:  return mobZeroB.w_string();
  case 41:  return mobZeroB.l_string();
  case 42:  return mobZeroB.p_string();
  case 43:  return mobVdd.string();
  case 44:  return mobVdd.w_string();
  case 45:  return mobVdd.l_string();
  case 46:  return mobVdd.p_string();
  case 47:  return mobVddB.string();
  case 48:  return mobVddB.w_string();
  case 49:  return mobVddB.l_string();
  case 50:  return mobVddB.p_string();
  case 51:  return mobVddD.string();
  case 52:  return mobVddD.w_string();
  case 53:  return mobVddD.l_string();
  case 54:  return mobVddD.p_string();
  case 55:  return ugs.string();
  case 56:  return ugs.w_string();
  case 57:  return ugs.l_string();
  case 58:  return ugs.p_string();
  case 59:  return ugsB.string();
  case 60:  return ugsB.w_string();
  case 61:  return ugsB.l_string();
  case 62:  return ugsB.p_string();
  case 63:  return uds.string();
  case 64:  return uds.w_string();
  case 65:  return uds.l_string();
  case 66:  return uds.p_string();
  case 67:  return udsB.string();
  case 68:  return udsB.w_string();
  case 69:  return udsB.l_string();
  case 70:  return udsB.p_string();
  case 71:  return udsD.string();
  case 72:  return udsD.w_string();
  case 73:  return udsD.l_string();
  case 74:  return udsD.p_string();
  case 75:  return n0.string();
  case 76:  return n0.w_string();
  case 77:  return n0.l_string();
  case 78:  return n0.p_string();
  case 79:  return nB.string();
  case 80:  return nB.w_string();
  case 81:  return nB.l_string();
  case 82:  return nB.p_string();
  case 83:  return nD.string();
  case 84:  return nD.w_string();
  case 85:  return nD.l_string();
  case 86:  return nD.p_string();
  case 87:  return dl_u.string();
  case 88:  return dw_u.string();
  case 89:  return tox_u.string();
  case 90:  return vdd.string();
  case 91:  return wdf.string();
  case 92:  return dell.string();
  case 93:  return temp.string();
  case 94:  return xpart.string();
  default: return MODEL_BUILT_IN_MOS_BASE::param_value(i);
  }
}
/*--------------------------------------------------------------------------*/
bool MODEL_BUILT_IN_MOS4::is_valid(const COMPONENT* d)const
{
  assert(d);
  return MODEL_BUILT_IN_MOS_BASE::is_valid(d);
}
/*--------------------------------------------------------------------------*/
void MODEL_BUILT_IN_MOS4::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_MOS4* s = prechecked_cast<const SDP_BUILT_IN_MOS4*>(c->sdp());
  assert(s);
  const MODEL_BUILT_IN_MOS4* m = this;

    trace3("", d->vds, d->vgs, d->vbs);
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
    d->reverse_if_needed();
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    trace4("", c->lo, m->dl, c->wo, m->dw);
    trace3("", s->ugs, s->ugsB, d->vbs);
    double Ugs = s->ugs + s->ugsB * d->vbs;
    double dUgsdVbs;
    if(Ugs <= 0) {
      untested();
      Ugs = 0;
      dUgsdVbs = 0.0;
    }else{
      dUgsdVbs = s->ugsB;
    }
    trace2("", Ugs, dUgsdVbs);
    
    double Uds = s->uds + s->udsB * d->vbs + s->udsD * (d->vds - m->vdd);
    double dUdsdVbs;
    double dUdsdVds;
    if(Uds <= 0) {    
      untested();
      Uds = 0.0;
      dUdsdVbs = dUdsdVds = 0.0;
    }else{
      double Leff = s->l_eff * 1e6; /* Leff in um */
      Uds  =  Uds / Leff;
      dUdsdVbs = s->udsB / Leff;
      dUdsdVds = s->udsD / Leff;
    }
    trace3("", Uds, dUdsdVbs, dUdsdVds);
    
    double Vpb;
    if(d->vbs <= 0) {
      Vpb = s->phi - d->vbs;
      d->sbfwd = false;
    }else{
      Vpb = s->phi;
      d->sbfwd = true;
    }
    double SqrtVpb = sqrt(Vpb);
    trace2("", Vpb, SqrtVpb);
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /* threshold voltage */
    double dVthdVbs;
    double dVthdVds;
    {
      double Eta = s->eta + s->etaB * d->vbs + s->etaD * (d->vds - m->vdd);
      double dEtadVds;
      double dEtadVbs;
      if(Eta <= 0) {   
	Eta  = 0; 
	dEtadVds = dEtadVbs = 0.0 ;
      }else if (Eta > 1) {
	untested();
	Eta = 1;
	dEtadVds = dEtadVbs = 0;
      }else{ 
	untested();
	dEtadVds = s->etaD;
	dEtadVbs = s->etaB;
      }
      trace3("", Eta, dEtadVds, dEtadVbs);
      d->von = s->vfb + s->phi + s->k1 * SqrtVpb - s->k2 * Vpb - Eta * d->vds;
      dVthdVds = -Eta - dEtadVds * d->vds;
      dVthdVbs = s->k2 - 0.5 * s->k1 / SqrtVpb - dEtadVbs * d->vds;
      d->vgst  = d->vgs - d->von;
      trace4("", d->von, dVthdVds, dVthdVbs, d->vgst);
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    double G = 1. - 1./(1.744+0.8364 * Vpb);
    double A = 1. + 0.5*G*s->k1/SqrtVpb;
    A = std::max(A, 1.0);   /* Modified */
    double Arg = std::max((1 + Ugs * d->vgst), 1.0);
    double dGdVbs = -0.8364 * (1-G) * (1-G);
    double dAdVbs = 0.25 * s->k1 / SqrtVpb *(2*dGdVbs + G/Vpb);
    trace3("", G, A, Arg);
    trace2("", dGdVbs, dAdVbs);
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /* ids and derivatives calculation */
    if (d->vgst < 0) {
      d->cutoff = true;
      /* cutoff */
      d->ids = 0;
      d->gmf = 0;
      d->gds = 0;
      d->gmbf = 0;
      d->vdsat = 0;
      trace4("cutoff", d->ids, d->gmf, d->gds, d->gmbf);
    }else{
      d->cutoff = false;
      /* Quadratic Interpolation for Beta0 (Beta at d->vgs  =  0, vds=Vds) */
      double Beta0;
      double dBeta0dVds;
      double dBeta0dVbs;
      {
	trace2("", m->tox, m->cox*1e-4);
	trace3("", s->betaVdd, s->betaVddB, d->vbs);
	double BetaVdd = (s->betaVdd + s->betaVddB * d->vbs);
	double dBetaVdd_dVds = std::max(s->betaVddD, 0.0); /* Modified */
	trace2("", BetaVdd, dBetaVdd_dVds);
	if(d->vds > m->vdd) {
	  Beta0      = BetaVdd + dBetaVdd_dVds * (d->vds - m->vdd);
	  dBeta0dVds = dBetaVdd_dVds;
	  dBeta0dVbs = s->betaVddB;
	  trace3("vds>vdd", Beta0, dBeta0dVds, dBeta0dVbs);
	}else{
	  double Beta_Vds_0 = (s->betaZero + s->betaZeroB * d->vbs);
	  double VddSquare = m->vdd * m->vdd;
	  double C1 = (-BetaVdd + Beta_Vds_0+dBetaVdd_dVds*m->vdd) / VddSquare;
	  double C2 = 2 * (BetaVdd - Beta_Vds_0) / m->vdd - dBetaVdd_dVds;
	  trace4("", Beta_Vds_0, VddSquare, C1, C2);
	  double dBeta_Vds_0_dVbs = s->betaZeroB;
	  double dBetaVdd_dVbs = s->betaVddB;
	  double dC1dVbs = (dBeta_Vds_0_dVbs - dBetaVdd_dVbs) / VddSquare;
	  double dC2dVbs = dC1dVbs * (-2) * m->vdd;
	  trace4("", dBeta_Vds_0_dVbs, dBetaVdd_dVbs, dC1dVbs, dC2dVbs);
	  Beta0	   = (C1 * d->vds + C2) * d->vds + Beta_Vds_0;
	  dBeta0dVds = 2*C1*d->vds + C2;
	  dBeta0dVbs = dC1dVbs * d->vds * d->vds 
	    + dC2dVbs * d->vds + dBeta_Vds_0_dVbs;
	  trace3("vds<vdd", Beta0, dBeta0dVds, dBeta0dVbs);
	}
      }
      
      /*Beta  =  Beta0 / ( 1 + Ugs * d->vgst );*/
      double Beta	     = Beta0 / Arg ;
      double dBetadVgs = -Beta * Ugs / Arg;
      double dBetadVds = dBeta0dVds / Arg - dBetadVgs * dVthdVds ;
      double dBetadVbs = dBeta0dVbs / Arg 
	+ Beta * Ugs * dVthdVbs / Arg - Beta * d->vgst * dUgsdVbs / Arg;
      trace4("", Beta, dBetadVgs, dBetadVds, dBetadVbs);
      
      /*d->vdsat  = std::max(d->vgst / ( A + Uds * d->vgst ),  0.0);*/
      double Vc = Uds * d->vgst / A;
      if(Vc < 0.0) {
	untested();
	Vc=0.0;
      }
      
      double Term1 = sqrt(1 + 2 * Vc);
      double K = 0.5 * (1 + Vc + Term1);
      d->vdsat = std::max(d->vgst / (A * sqrt(K)) , 0.0);
      trace4("", Vc, Term1, K, d->vdsat);
      
      if(d->vds < d->vdsat) {		/* Triode Region */
	d->saturated = false;
	/*Argl1  =  1 + Uds * d->vds;*/
	double Argl1 = std::max((1 + Uds * d->vds), 1.);
	double Argl2 = d->vgst - 0.5 * A * d->vds;
	trace2("", Argl1, Argl2);
	d->ids = Beta * Argl2 * d->vds / Argl1;
	d->gmf   = (dBetadVgs * Argl2 * d->vds + Beta * d->vds) / Argl1;
	d->gds  = (dBetadVds * Argl2 * d->vds 
		   + Beta * (d->vgst - d->vds * dVthdVds - A * d->vds)
		   - d->ids * (d->vds * dUdsdVds + Uds)) /  Argl1;
	d->gmbf = (dBetadVbs * Argl2 * d->vds 
		  + Beta * d->vds * (-dVthdVbs - 0.5 * d->vds * dAdVbs)
		  - d->ids * d->vds * dUdsdVbs) / Argl1;
	trace4("triode", d->ids, d->gmf, d->gds, d->gmbf);
      }else{			/* Pinchoff (Saturation) Region */
	d->saturated = true;
	double Args1   =  1. + 1. / Term1;
	double dVcdVgs =  Uds / A;
	double dVcdVds =  d->vgst * dUdsdVds / A - dVcdVgs * dVthdVds;
	double dVcdVbs =  (d->vgst * dUdsdVbs 
			   - Uds * (dVthdVbs + d->vgst * dAdVbs / A )) / A;
	double dKdVc   =  0.5 * Args1;
	double dKdVgs  =  dKdVc * dVcdVgs;
	double dKdVds  =  dKdVc * dVcdVds;
	double dKdVbs  =  dKdVc * dVcdVbs;
	double Args2   =  d->vgst / A / K;
	double Args3   =  Args2 * d->vgst;
	trace3("", Args1, Args2, Args3);
	trace3("", dVcdVgs, dVcdVds, dVcdVbs);
	trace4("", dKdVc, dKdVgs, dKdVds, dKdVbs);
	d->ids =  0.5 * Beta * Args3;
	d->gmf = 0.5 * Args3 * dBetadVgs + Beta * Args2 - d->ids * dKdVgs / K;
	d->gds = 0.5*Args3*dBetadVds - Beta*Args2*dVthdVds - d->ids*dKdVds/K;
	d->gmbf = 0.5 * dBetadVbs * Args3 - Beta * Args2 *dVthdVbs
	  - d->ids * (dAdVbs / A + dKdVbs / K);
	trace4("sat", d->ids, d->gmf, d->gds, d->gmbf);
      }
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /* SubthresholdComputation */
    
    /* The following 'if' statement has been modified so that subthreshold  *
     * current computation is always executed unless N0 >= 200. This should *
     * get rid of the Ids kink seen on Ids-Vgs plots at low Vds.            *
     *                                                Peter M. Lee          *
     *                                                6/8/90                *
     *  Old 'if' statement:  (reversed)                                     *
     *  if( (N0 >=  200) || (d->vgst < Vcut ) || (d->vgst > (-0.5*Vcut)))   */
    
    //double Vcut  =  - 40. * s->n0 * t->vt ;
    if (s->n0 < 200) {
      double N = s->n0 + s->nB*d->vbs + s->nD*d->vds; /* subthreshold slope */
      trace4("", s->n0, s->nB, s->nD, N);
      if (N < 0.5) {
	untested();
	N = 0.5;
      }
      const double ref_temp = 300.15; // ignore real temp for spice compatibility
      const double vt0 = ref_temp * P_K_Q;
      const double Vtsquare = vt0 * vt0 ;
      const double nvt0 = N * vt0;
      double Warg1 = exp(-d->vds / vt0);
      double Wds   = 1 - Warg1;
      double Wgs   = exp( d->vgst / nvt0);
      double Warg2  = 6.04965 * Vtsquare * s->betaZero;
      double Ilimit = 4.5 * Vtsquare * s->betaZero;
      double Iexp   = Warg2 * Wgs * Wds;
      d->ids += Ilimit * Iexp / (Ilimit + Iexp);
      double Temp1  = Ilimit / (Ilimit + Iexp);
      Temp1  =  Temp1 * Temp1;
      double Temp3  = Ilimit / (Ilimit + Wgs * Warg2);
      Temp3 = Temp3 * Temp3 * Warg2 * Wgs;
      /*    if ( Temp3 > Ilimit ) Temp3=Ilimit;*/
      d->gmf  += Temp1 * Iexp / nvt0;
      /* gds term has been modified to prevent blow up at Vds=0 */
      d->gds += Temp3
	* (Wds / nvt0 * (dVthdVds + d->vgst * s->nD / N)
	   + Warg1 / vt0);
      d->gmbf -= Temp1 * Iexp * (dVthdVbs + d->vgst * s->nB / N) / nvt0;
      trace3("", vt0, Vtsquare, nvt0);
      trace4("", Warg1, Wds, Wgs, Warg2);
      trace4("", Ilimit, Iexp, Temp1, Temp3);
      trace4("sub", d->ids, d->gmf, d->gds, d->gmbf);
    }else{
      untested();
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /* Some Limiting of DC Parameters */
    if(d->ids < 0.0) d->ids = 0.0;
    if(d->gmf  < 0.0) d->gmf  = 0.0;
    if(d->gds < 0.0) d->gds = 0.0;
    if(d->gmbf < 0.0) d->gmbf = 0.0;
    trace4("final", d->ids, d->gmf, d->gds, d->gmbf);

    trace3("", G, A, s->phi);
    trace1("", m->xpart);
    
    double Vth0 = s->vfb + s->phi + s->k1 * SqrtVpb; // almost same as d->von
    double Vgs_Vth = d->vgs - Vth0; // almost same as d->vgst
    trace2("", Vth0, Vgs_Vth);
    double Arg1 = A * d->vds;
    double Arg2 = Vgs_Vth - 0.5 * Arg1;
    double Arg3 = d->vds - Arg1;
    trace3("", Arg1, Arg2, Arg3);
    /*double*/ dVthdVbs = -0.5 * s->k1 / SqrtVpb;
    /*dbl*/ dAdVbs = 0.5 * s->k1 * (0.5*G/Vpb - 0.8364*(1-G)*(1-G)) / SqrtVpb;
    trace2("", dVthdVbs, dAdVbs);
    double Ent = std::max(Arg2,1.0e-8);
    double dEntdVds = -0.5 * A;
    double dEntdVbs = -dVthdVbs - 0.5 * d->vds * dAdVbs;
    trace3("", Ent, dEntdVds, dEntdVbs);
    double VdsPinchoff = std::max(Vgs_Vth / A, 0.0);
    double Vgb  = d->vgs - d->vbs ;
    double Vgb_Vfb  = Vgb - s->vfb;
    trace3("", VdsPinchoff, Vgb, Vgb_Vfb);
    
    if(Vgb_Vfb < 0) {			/* Accumulation Region */
      untested();
      d->qgate = s->cgate * Vgb_Vfb;
      d->qbulk = -d->qgate;
      d->qdrn  = 0. ;
      d->cggb = s->cgate;
      d->cgdb = 0.;
      d->cgsb = 0.;
      d->cbgb = -s->cgate;
      d->cbdb = 0.;
      d->cbsb = 0.;
      d->cdgb = 0.;
      d->cddb = 0.;
      d->cdsb = 0.;
      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->vgs < Vth0) {		/* Subthreshold Region */
      d->qgate = 0.5*s->cgate*s->k1*s->k1*(-1+sqrt(1+4*Vgb_Vfb/(s->k1*s->k1)));
      d->cggb = s->cgate / sqrt(1 + 4 * Vgb_Vfb / (s->k1 * s->k1));
      d->cgdb = d->cgsb = 0.;
      d->qbulk = -d->qgate;
      d->cbgb = -d->cggb;
      d->cbdb = d->cbsb = 0.0;
      d->qdrn = 0.;
      d->cdgb = d->cddb = d->cdsb = 0.0;
      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 if (d->vds < VdsPinchoff) {	/* triode region */
      double EntSquare = Ent * Ent;
      trace1("tri", EntSquare);
      double Argl1 = 1.2e1 * EntSquare;
      double Argl2 = 1.0 - A;
      double Argl3 = Arg1 * d->vds;
      trace3("", Argl1, Argl2, Argl3);
      double Argl5;
      if (Ent > 1.0e-8) {
	Argl5 = Arg1 / Ent;
      }else{   
	untested();
	Argl5 = 2.0;
      }
      double Argl7 = Argl5 / 1.2e1;
      double Argl8 = 6.0 * Ent;
      trace3("", Argl5, Argl7, Argl8);
      
      d->qgate = s->cgate 
	* (d->vgs - s->vfb - s->phi - 0.5 * d->vds + d->vds * Argl7);
      d->cggb = s->cgate * (1.0 - Argl3 / Argl1);
      d->cgdb = s->cgate * (-0.5 + Arg1 / Argl8 - Argl3 * dEntdVds / Argl1);
      double cgbb = s->cgate * (d->vds*d->vds*dAdVbs*Ent-Argl3*dEntdVbs)/Argl1;
      d->cgsb = -(d->cggb + d->cgdb + cgbb);
      trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
      
      d->qbulk = s->cgate * (-Vth0 + s->vfb + s->phi + 0.5*Arg3 - Arg3*Argl7);
      d->cbgb = s->cgate * Argl3 * Argl2 / Argl1;
      d->cbdb = s->cgate * Argl2 * (0.5 - Arg1/Argl8 + Argl3 * dEntdVds/Argl1);
      double cbbb = -s->cgate * (dVthdVbs + 0.5 * d->vds * dAdVbs
	       +d->vds*d->vds*((1.0-2.0*A)*dAdVbs*Ent-Argl2*A*dEntdVbs)/Argl1);
      d->cbsb = -(d->cbgb + d->cbdb + cbbb);
      trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
      
      if (m->xpart >= 1) {
	/*0/100 partitioning for drain/source chArges at saturation region*/
	double Argl9 = 0.125 * Argl5 * Argl5; //t
	d->qdrn = -s->cgate * (0.5*Vgs_Vth - 0.75*Arg1 + 0.125*Arg1*Argl5);
	d->cdgb = -s->cgate * (0.5 - Argl9);
	d->cddb = s->cgate * (0.75*A - 0.25*A*Arg1/Ent + Argl9*dEntdVds);
	double cdbb = s->cgate * (0.5 * dVthdVbs + d->vds * dAdVbs * 
				  (0.75 - 0.25 * Argl5 ) + Argl9 * dEntdVbs);
	d->cdsb = -(d->cdgb + d->cddb + cdbb);
	trace2("", Argl9, cdbb);
	trace4("tri 0/100", d->qdrn, d->cdgb, d->cddb, d->cdsb);
      }else{
	/*40/60 partitioning for drain/source chArges at saturation region*/
	double Vgs_VthSquare = Vgs_Vth*Vgs_Vth;
	trace2("", Vgs_Vth, Vgs_VthSquare);
	double Arg5 = Arg1*Arg1;
	double Vcom = Vgs_Vth*Vgs_Vth/6.0-1.25e-1*Arg1*Vgs_Vth+2.5e-2*Arg5;
	double Argl4 = Vcom/Ent/EntSquare;
	double Argl6;
	if (Ent > 1.0e-8) {
	  Argl6 = Vcom / EntSquare;
	}else{   
	  untested();
	  Argl6 = 4.0 / 1.5e1;
	}
	d->qdrn = -s->cgate * (0.5 * (Vgs_Vth-Arg1) + Arg1 * Argl6);
	d->cdgb = -s->cgate
	  * (0.5 + Arg1*(4.0*Vgs_Vth-1.5*Arg1)/Argl1 - 2.0*Arg1*Argl4);
	d->cddb = s->cgate*(0.5*A+2.0*Arg1*dEntdVds*Argl4-A*(2.0*Vgs_VthSquare
					-3.0*Arg1*Vgs_Vth+0.9*Arg5)/Argl1);
	double cdbb =s->cgate*(0.5*dVthdVbs+0.5*d->vds*dAdVbs+2.0*Arg1*dEntdVbs
	     *Argl4-d->vds*(2.0*Vgs_VthSquare*dAdVbs-4.0*A*Vgs_Vth*dVthdVbs-3.0
	     *Arg1*Vgs_Vth*dAdVbs+1.5*A*Arg1*dVthdVbs+0.9*Arg5*dAdVbs)
			       /Argl1);
	d->cdsb = -(d->cdgb + d->cddb + cdbb);
	trace4("", Vcom, Argl4, Argl6, cdbb);
	trace4("lin 40/60", d->qdrn, d->cdgb, d->cddb, d->cdsb);
      }
    }else{				/* saturation region */
      assert(d->vds >= VdsPinchoff);
      double Args1 = 1.0 / (3.0 * A);
      trace2("sat", s->cgate, Args1);
      
      d->qgate = s->cgate * (d->vgs - s->vfb - s->phi - Vgs_Vth * Args1);
      d->cggb = s->cgate * (1.0 - Args1);
      d->cgdb = 0.0;
      double cgbb = s->cgate * Args1 * (dVthdVbs + Vgs_Vth * dAdVbs / A);
      d->cgsb = -(d->cggb + d->cgdb + cgbb);
      trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
      
      d->qbulk = s->cgate * (s->vfb + s->phi - Vth0 + (1.0-A)*Vgs_Vth*Args1);
      d->cbgb = s->cgate * (Args1 - 1.0 / 3.0);
      d->cbdb = 0.0;
      double cbbb = -s->cgate * ((2.0 / 3.0 + Args1) * dVthdVbs
				 + Vgs_Vth * Args1 * dAdVbs / A);
      d->cbsb = -(d->cbgb + d->cbdb + cbbb);
      trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
      
      if (m->xpart >= 1) {
	/*0/100 partitioning for drain/source chArges at saturation region*/
	d->qdrn = 0.0;
	d->cdgb = 0.0;
	d->cddb = 0.0;
	d->cdsb = 0.0;
	trace4("sat 0/100", d->qdrn, d->cdgb, d->cddb, d->cdsb);
      }else{
	/*40/60 partitioning for drain/source chArges at saturation region*/
	const double co4v15 = 4./15.;
	d->qdrn = -co4v15 * s->cgate * Vgs_Vth;
	d->cdgb = -co4v15 * s->cgate;
	d->cddb =  0.0;
	double cdbb = co4v15 * s->cgate * dVthdVbs;
	d->cdsb = -(d->cdgb + d->cddb + cdbb);
	trace4("sat 40/60", 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.;
    }
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
