1 /* $Id: u_limit.h,v 26.81 2008/05/27 05:34:00 al Exp $ -*- C++ -*-
2 * Copyright (C) 2006 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * device limiting library
24 //testing=script 2006.07.14
28 /*--------------------------------------------------------------------------*/
29 /* Spice style PN junction limiting */
30 inline double pnj_limit(double vnew
, double vold
, double vt
, double vcrit
)
32 trace4("limit-in", vnew
, vold
, vt
, vcrit
);
33 if ((vnew
> vcrit
) && (std::abs(vnew
- vold
) > (2 * vt
))) {
35 double arg
= 1 + (vnew
- vold
) / vt
;
36 double vlim
= (arg
> 0) ? (vold
+ vt
* log(arg
)) : vcrit
;
37 trace3("limit-1", vlim
, vt
*log(arg
), arg
);
40 double vlim
= vt
* log(vnew
/vt
);
41 trace3("limit-2", vlim
, vt
*log(vnew
/vt
), vnew
/vt
);
45 trace1("limit-3", vnew
);
49 /*--------------------------------------------------------------------------*/
50 inline double fet_limit_vds(double vnew
, double vold
)
53 if (vnew
> (3*vold
+ 2)) {itested();
63 }else if (vnew
< -.5) {
70 /*--------------------------------------------------------------------------*/
71 inline double fet_limit_vgs(double vnew
, double vold
, double vto
)
76 double vgst_old
= vold
- vto
;
77 double vgst_new
= vnew
- vto
;
79 if (vgst_old
>= 3.5) { /* was strong on */
82 }else if (vgst_new
> (3 * vgst_old
+ 2)) {itested();
83 v_limited
= 3*vgst_old
+ 2;
87 }else if (vgst_old
>= 0) { /* middle region, on */
88 assert(vgst_old
< 3.5);
91 }else if (vgst_new
> 4) {
96 }else if (vgst_old
<= 0) { /* was off, vgst_old < 0 */
98 if (vgst_new
< (3 * vgst_old
- 2)) {
99 v_limited
= 3*vgst_old
- 2;
100 }else if (vgst_new
> .5) {
103 v_limited
= vgst_new
;
105 }else{ /* overflow or other numeric error */
106 // not sure what to do in this case.
107 // It could actually happen with overflow or divide by zero.
108 // but supposedly this is trapped elsewhere.
111 trace3("huh?", vnew
, vold
, vto
);
112 trace3(" ", vgst_new
, vgst_old
, v_limited
);
114 return v_limited
+ vto
;
116 /*--------------------------------------------------------------------------*/
117 /*--------------------------------------------------------------------------*/
119 // vim:ts=8:sw=2:noet: