LCOV - code coverage report
Current view: top level - src/components/devices - diode.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 203 231 87.9 %
Date: 2015-01-05 16:01:02 Functions: 16 20 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 73 154 47.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * diode.cpp - diode class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Stefan Jahn <stefan@lkcc.org>
       5                 :            :  *
       6                 :            :  * This is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU General Public License as published by
       8                 :            :  * the Free Software Foundation; either version 2, or (at your option)
       9                 :            :  * any later version.
      10                 :            :  *
      11                 :            :  * This software is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with this package; see the file COPYING.  If not, write to
      18                 :            :  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
      19                 :            :  * Boston, MA 02110-1301, USA.
      20                 :            :  *
      21                 :            :  * $Id$
      22                 :            :  *
      23                 :            :  */
      24                 :            : 
      25                 :            : #if HAVE_CONFIG_H
      26                 :            : # include <config.h>
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include "component.h"
      30                 :            : #include "device.h"
      31                 :            : #include "devstates.h"
      32                 :            : #include "diode.h"
      33                 :            : 
      34                 :            : #define NODE_C 0 /* cathode node */
      35                 :            : #define NODE_A 1 /* anode node   */
      36                 :            : 
      37                 :            : #define StateVars 1 // state variables
      38                 :            : 
      39                 :            : // state variable indices
      40                 :            : #define _UdPrev 0
      41                 :            : 
      42                 :            : // state variable shortcuts
      43                 :            : #define UdPrev deviceVar (_UdPrev)
      44                 :            : 
      45                 :            : using namespace qucs;
      46                 :            : using namespace qucs::device;
      47                 :            : 
      48                 :            : // Constructor for the diode.
      49 [ +  - ][ #  # ]:         28 : diode::diode () : circuit (2) {
      50                 :         28 :   rs = NULL;
      51                 :         28 :   type = CIR_DIODE;
      52                 :         28 : }
      53                 :            : 
      54                 :            : // Callback for S-parameter analysis.
      55                 :        400 : void diode::calcSP (nr_double_t frequency) {
      56         [ +  - ]:        400 :   nr_double_t gd = getOperatingPoint ("gd");
      57         [ +  - ]:        400 :   nr_double_t Cd = getOperatingPoint ("Cd");
      58                 :        400 :   nr_complex_t y = 2 * z0 * nr_complex_t (gd, Cd * 2.0 * M_PI * frequency);
      59 [ +  - ][ +  - ]:        400 :   setS (NODE_C, NODE_C, 1.0 / (1.0 + y));
      60 [ +  - ][ +  - ]:        400 :   setS (NODE_A, NODE_A, 1.0 / (1.0 + y));
      61 [ +  - ][ +  - ]:        400 :   setS (NODE_C, NODE_A, y / (1.0 + y));
      62 [ +  - ][ +  - ]:        400 :   setS (NODE_A, NODE_C, y / (1.0 + y));
      63                 :        400 : }
      64                 :            : 
      65                 :            : // Callback for S-parameter noise analysis.
      66                 :          0 : void diode::calcNoiseSP (nr_double_t frequency) {
      67                 :            : #if MICHAEL /* shot noise only */
      68                 :            :   nr_double_t Id = getOperatingPoint ("Id");
      69                 :            :   nr_double_t Is = getPropertyDouble ("Is") + getPropertyDouble ("Isr");
      70                 :            : 
      71                 :            :   // adjust shot noise current if necessary
      72                 :            :   if (Id < -Is) Id = -Is;
      73                 :            : 
      74                 :            :   nr_double_t gd = getOperatingPoint ("gd");
      75                 :            :   nr_double_t Cd = getOperatingPoint ("Cd");
      76                 :            : 
      77                 :            :   nr_complex_t y = rect (gd, Cd * 2.0 * M_PI * frequency);
      78                 :            :   nr_complex_t f = 2 * z0 * (Id + 2 * Is) / norm (2 * z0 * y + 1) * QoverkB / T0;
      79                 :            :   setN (NODE_C, NODE_C, +f); setN (NODE_A, NODE_A, +f);
      80                 :            :   setN (NODE_C, NODE_A, -f); setN (NODE_A, NODE_C, -f);
      81                 :            : #else
      82 [ #  # ][ #  # ]:          0 :   setMatrixN (cytocs (calcMatrixCy (frequency) * z0, getMatrixS ()));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      83                 :            : #endif
      84                 :          0 : }
      85                 :            : 
      86                 :            : // Computes noise correlation matrix Cy.
      87                 :          0 : matrix diode::calcMatrixCy (nr_double_t frequency) {
      88                 :            :   // fetch computed operating points
      89                 :          0 :   nr_double_t Id = getOperatingPoint ("Id");
      90                 :          0 :   nr_double_t Is = getPropertyDouble ("Is") + getPropertyDouble ("Isr");
      91                 :            : 
      92                 :            :   // adjust shot noise current if necessary
      93         [ #  # ]:          0 :   if (Id < -Is) Id = -Is;
      94                 :            : 
      95                 :          0 :   nr_double_t Kf  = getPropertyDouble ("Kf");
      96                 :          0 :   nr_double_t Af  = getPropertyDouble ("Af");
      97                 :          0 :   nr_double_t Ffe = getPropertyDouble ("Ffe");
      98                 :            : 
      99                 :            :   // build noise current correlation matrix
     100                 :          0 :   matrix cy (2);
     101                 :            :   nr_double_t i = 2 * (Id + 2 * Is) * QoverkB / T0 +    // shot noise
     102 [ #  # ][ #  # ]:          0 :     Kf * qucs::pow (fabs (Id), Af) / qucs::pow (frequency, Ffe) / kB / T0; // flicker noise
     103 [ #  # ][ #  # ]:          0 :   cy.set (NODE_C, NODE_C, +i); cy.set (NODE_A, NODE_A, +i);
     104 [ #  # ][ #  # ]:          0 :   cy.set (NODE_A, NODE_C, -i); cy.set (NODE_C, NODE_A, -i);
     105                 :          0 :   return cy;
     106                 :            : }
     107                 :            : 
     108                 :            : // Initializes the diode model including temperature and area effects.
     109                 :      12153 : void diode::initModel (void) {
     110                 :            :   // fetch necessary device properties
     111                 :      12153 :   nr_double_t T  = getPropertyDouble ("Temp");
     112                 :      12153 :   nr_double_t Tn = getPropertyDouble ("Tnom");
     113                 :      12153 :   nr_double_t A  = getPropertyDouble ("Area");
     114                 :            : 
     115                 :            :   // compute Is temperature and area dependency
     116                 :      12153 :   nr_double_t Is  = getPropertyDouble ("Is");
     117                 :      12153 :   nr_double_t N   = getPropertyDouble ("N");
     118                 :      12153 :   nr_double_t Xti = getPropertyDouble ("Xti");
     119                 :      12153 :   nr_double_t Eg  = getPropertyDouble ("Eg");
     120                 :            :   nr_double_t T1, T2;
     121                 :      12153 :   T2 = kelvin (T);
     122                 :      12153 :   T1 = kelvin (Tn);
     123                 :      12153 :   Is = pnCurrent_T (T1, T2, Is, Eg, N, Xti);
     124                 :      12153 :   setScaledProperty ("Is", Is * A);
     125                 :            : 
     126                 :            :   // compute Isr temperature and area dependency
     127                 :      12153 :   nr_double_t Isr = getPropertyDouble ("Isr");
     128                 :      12153 :   nr_double_t Nr  = getPropertyDouble ("Nr");
     129                 :      12153 :   Isr = pnCurrent_T (T1, T2, Isr, Eg, Nr, Xti);
     130                 :      12153 :   setScaledProperty ("Isr", Isr * A);
     131                 :            : 
     132                 :            :   // check unphysical parameters
     133         [ -  + ]:      12153 :   if (Nr < 1.0) {
     134                 :            :     logprint (LOG_ERROR, "WARNING: Unphysical model parameter Nr = %g in "
     135                 :          0 :               "diode `%s'\n", Nr, getName ());
     136                 :            :   }
     137         [ -  + ]:      12153 :   if (N < 1.0) {
     138                 :            :     logprint (LOG_ERROR, "WARNING: Unphysical model parameter N = %g in "
     139                 :          0 :               "diode `%s'\n", N, getName ());
     140                 :            :   }
     141                 :            : 
     142                 :            :   // compute Vj temperature dependency
     143                 :      12153 :   nr_double_t Vj = getPropertyDouble ("Vj");
     144                 :            :   nr_double_t VjT;
     145                 :      12153 :   VjT = pnPotential_T (T1,T2, Vj);
     146                 :      12153 :   setScaledProperty ("Vj", VjT);
     147                 :            : 
     148                 :            :   // compute Cj0 temperature and area dependency
     149                 :      12153 :   nr_double_t Cj0 = getPropertyDouble ("Cj0");
     150                 :      12153 :   nr_double_t M   = getPropertyDouble ("M");
     151                 :      12153 :   Cj0 = pnCapacitance_T (T1, T2, M, VjT / Vj, Cj0);
     152                 :      12153 :   setScaledProperty ("Cj0", Cj0 * A);
     153                 :            : 
     154                 :            :   // check unphysical parameters
     155         [ -  + ]:      12153 :   if (M > 1.0) {
     156                 :            :     logprint (LOG_ERROR, "WARNING: Unphysical model parameter M = %g in "
     157                 :          0 :               "Diode `%s'\n", M, getName ());
     158                 :            :   }
     159                 :            : 
     160                 :            :   // compute Bv temperature dependency
     161                 :      12153 :   nr_double_t Bv  = getPropertyDouble ("Bv");
     162                 :      12153 :   nr_double_t Tbv = getPropertyDouble ("Tbv");
     163                 :      12153 :   nr_double_t DT  = T2 - T1;
     164                 :      12153 :   Bv = Bv - Tbv * DT;
     165                 :      12153 :   setScaledProperty ("Bv", Bv);
     166                 :            : 
     167                 :            :   // compute Tt temperature dependency
     168                 :      12153 :   nr_double_t Tt   = getPropertyDouble ("Tt");
     169                 :      12153 :   nr_double_t Ttt1 = getPropertyDouble ("Ttt1");
     170                 :      12153 :   nr_double_t Ttt2 = getPropertyDouble ("Ttt2");
     171                 :      12153 :   Tt = Tt * (1 + Ttt1 * DT + Ttt2 * DT * DT);
     172                 :      12153 :   setScaledProperty ("Tt", Tt);
     173                 :            : 
     174                 :            :   // compute M temperature dependency
     175                 :      12153 :   nr_double_t Tm1 = getPropertyDouble ("Tm1");
     176                 :      12153 :   nr_double_t Tm2 = getPropertyDouble ("Tm2");
     177                 :      12153 :   M = M * (1 + Tm1 * DT + Tm2 * DT * DT);
     178                 :      12153 :   setScaledProperty ("M", M);
     179                 :            : 
     180                 :            :   // compute Rs temperature and area dependency
     181                 :      12153 :   nr_double_t Rs  = getPropertyDouble ("Rs");
     182                 :      12153 :   nr_double_t Trs = getPropertyDouble ("Trs");
     183                 :      12153 :   Rs = Rs * (1 + Trs * DT);
     184                 :      12153 :   setScaledProperty ("Rs", Rs / A);
     185                 :      12153 : }
     186                 :            : 
     187                 :            : // Prepares DC (i.e. HB) analysis.
     188                 :      12153 : void diode::prepareDC (void) {
     189                 :            :   // allocate MNA matrices
     190                 :      12153 :   allocMatrixMNA ();
     191                 :            : 
     192                 :            :   // initialize scalability
     193                 :      12153 :   initModel ();
     194                 :            : 
     195                 :            :   // initialize starting values
     196 [ +  - ][ +  - ]:      12153 :   Ud = real (getV (NODE_A) - getV (NODE_C));
     197         [ +  + ]:      24321 :   for (int i = 0; i < deviceStates (); i++) {
     198                 :      12168 :     deviceState (i);
     199                 :      12168 :     UdPrev = Ud;
     200                 :            :   }
     201                 :            : 
     202                 :            :   // get device temperature
     203                 :      12153 :   nr_double_t T = getPropertyDouble ("Temp");
     204                 :            : 
     205                 :            :   // possibly insert series resistance
     206                 :      12153 :   nr_double_t Rs = getScaledProperty ("Rs");
     207         [ +  + ]:      12153 :   if (Rs != 0.0) {
     208                 :            :     // create additional circuit if necessary and reassign nodes
     209                 :         12 :     rs = splitResistor (this, rs, "Rs", "anode", NODE_A);
     210                 :         12 :     rs->setProperty ("Temp", T);
     211                 :         12 :     rs->setProperty ("R", Rs);
     212                 :         12 :     rs->setProperty ("Controlled", getName ());
     213                 :         12 :     rs->initDC ();
     214                 :            :   }
     215                 :            :   // no series resistance
     216                 :            :   else {
     217                 :      12141 :     disableResistor (this, rs, NODE_A);
     218                 :            :   }
     219                 :            : 
     220                 :            :   // calculate actual breakdown voltage
     221                 :      12153 :   Bv = getScaledProperty ("Bv");
     222         [ +  + ]:      12153 :   if (Bv != 0) {
     223                 :            :     nr_double_t Ibv, Is, tol, Ut, Xbv, Xibv;
     224                 :        104 :     Ibv = getPropertyDouble ("Ibv");
     225                 :        104 :     Is = getScaledProperty ("Is");
     226                 :        104 :     Ut = kelvin (T) * kBoverQ;
     227                 :            :     // adjust very small breakdown currents
     228         [ -  + ]:        104 :     if (Ibv < Is * Bv / Ut) {
     229                 :          0 :       Ibv = Is * Bv / Ut;
     230                 :          0 :       Xbv = Bv;
     231                 :            :       logprint (LOG_ERROR, "WARNING: Increased breakdown current to %g to "
     232                 :          0 :                 "match the saturation current %g\n", Ibv, Is);
     233                 :            :     }
     234                 :            :     // fit reverse and forward regions
     235                 :            :     else {
     236                 :        104 :       int good = 0;
     237                 :        104 :       tol = 1e-3 * Ibv;
     238                 :        104 :       Xbv = Bv - Ut * qucs::log (1 + Ibv / Is);
     239         [ +  - ]:        104 :       for (int i = 0; i < 25 ; i++) {
     240                 :        104 :         Xbv = Bv - Ut * qucs::log (Ibv / Is + 1 - Xbv / Ut);
     241                 :        104 :         Xibv = Is * (qucs::exp ((Bv - Xbv) / Ut) - 1 + Xbv / Ut);
     242         [ +  - ]:        104 :         if (fabs (Xibv - Ibv) < tol) {
     243                 :        104 :           Bv = Xbv;
     244                 :        104 :           good = 1;
     245                 :        104 :           break;
     246                 :            :         }
     247                 :            :       }
     248         [ -  + ]:        104 :       if (!good) {
     249                 :            :         logprint (LOG_ERROR, "WARNING: Unable to fit reverse and forward "
     250                 :          0 :                   "diode regions using Bv=%g and Ibv=%g\n", Bv, Ibv);
     251                 :            :       }
     252                 :            :     }
     253                 :            :   }
     254                 :      12153 : }
     255                 :            : 
     256                 :            : // Callback for initializing the DC analysis.
     257                 :      12152 : void diode::initDC (void) {
     258                 :      12152 :   deviceStates (StateVars, 1);
     259                 :      12152 :   doHB = false;
     260                 :      12152 :   prepareDC ();
     261                 :      12152 : }
     262                 :            : 
     263                 :            : // Callback for restarting the DC analysis.
     264                 :       7394 : void diode::restartDC (void) {
     265                 :            :   // apply starting value to previous iteration value
     266 [ +  - ][ +  - ]:       7394 :   UdPrev = real (getV (NODE_A) - getV (NODE_C));
     267                 :       7394 : }
     268                 :            : 
     269                 :            : // Callback for DC analysis.
     270                 :     375133 : void diode::calcDC (void) {
     271                 :            :   // get device properties
     272                 :     375133 :   nr_double_t Is  = getScaledProperty ("Is");
     273                 :     375133 :   nr_double_t N   = getPropertyDouble ("N");
     274                 :     375133 :   nr_double_t Isr = getScaledProperty ("Isr");
     275                 :     375133 :   nr_double_t Nr  = getPropertyDouble ("Nr");
     276                 :     375133 :   nr_double_t Ikf = getPropertyDouble ("Ikf");
     277                 :     375133 :   nr_double_t T   = getPropertyDouble ("Temp");
     278                 :            : 
     279                 :            :   nr_double_t Ut, Ieq, Ucrit, gtiny;
     280                 :            : 
     281                 :     375133 :   T = kelvin (T);
     282                 :     375133 :   Ut = T * kBoverQ;
     283 [ +  - ][ +  - ]:     375133 :   Ud = real (getV (NODE_A) - getV (NODE_C));
     284                 :            : 
     285                 :            :   // critical voltage necessary for bad start values
     286                 :     375133 :   Ucrit = pnCriticalVoltage (Is, N * Ut);
     287 [ +  + ][ +  + ]:     375133 :   if (Bv != 0 && Ud < MIN (0, -Bv + 10 * N * Ut)) {
                 [ +  + ]
     288                 :       2650 :     nr_double_t V = -(Ud + Bv);
     289                 :       2650 :     V = pnVoltage (V, -(UdPrev + Bv), Ut * N, Ucrit);
     290                 :       2650 :     Ud = -(V + Bv);
     291                 :            :   }
     292                 :            :   else {
     293                 :     372483 :     Ud = pnVoltage (Ud, UdPrev, Ut * N, Ucrit);
     294                 :            :   }
     295                 :     375133 :   UdPrev = Ud;
     296                 :            : 
     297                 :            :   // tiny derivative for little junction voltage
     298 [ +  + ][ +  + ]:     375133 :   gtiny = (Ud < - 10 * Ut * N && Bv != 0) ? (Is + Isr) : 0;
     299                 :            : 
     300         [ +  + ]:     375133 :   if (Ud >= -3 * N * Ut) { // forward region
     301                 :     234303 :     gd = pnConductance (Ud, Is, Ut * N) + pnConductance (Ud, Isr, Ut * Nr);
     302                 :     234303 :     Id = pnCurrent (Ud, Is, Ut * N) + pnCurrent (Ud, Isr, Ut * Nr);
     303                 :            :   }
     304 [ +  + ][ +  + ]:     140830 :   else if (Bv == 0 || Ud >= -Bv) { // reverse region
     305                 :     138219 :     nr_double_t a = 3 * N * Ut / (Ud * M_E);
     306                 :     138219 :     a = cubic (a);
     307                 :     138219 :     Id = -Is * (1 + a);
     308                 :     138219 :     gd = +Is * 3 * a / Ud;
     309                 :            :   }
     310                 :            :   else { // middle region
     311                 :       2611 :     nr_double_t a = qucs::exp (-(Bv + Ud) / N / Ut);
     312                 :       2611 :     Id = -Is * a;
     313                 :       2611 :     gd = +Is * a / Ut / N;
     314                 :            :   }
     315                 :            : 
     316                 :            :   // knee current calculations
     317         [ -  + ]:     375133 :   if (Ikf != 0.0) {
     318                 :          0 :     nr_double_t a = Ikf / (Ikf + Id);
     319                 :          0 :     gd *= 0.5 * (2 - Id * a / Ikf) * qucs::sqrt (a);
     320                 :          0 :     Id *= qucs::sqrt (a);
     321                 :            :   }
     322                 :            : 
     323                 :     375133 :   Id += gtiny * Ud;
     324                 :     375133 :   gd += gtiny;
     325                 :            : 
     326                 :            :   // HB simulation
     327         [ +  + ]:     375133 :   if (doHB) {
     328                 :        176 :     Ieq = Id;
     329         [ +  - ]:        176 :     setGV (NODE_C, -gd * Ud);
     330         [ +  - ]:        176 :     setGV (NODE_A, +gd * Ud);
     331                 :            :   }
     332                 :            :   // DC and transient simulation
     333                 :            :   else {
     334                 :     374957 :     Ieq = Id - Ud * gd;
     335                 :            :   }
     336                 :            : 
     337                 :            :   // fill in I-Vector
     338         [ +  - ]:     375133 :   setI (NODE_C, +Ieq);
     339         [ +  - ]:     375133 :   setI (NODE_A, -Ieq);
     340                 :            : 
     341                 :            :   // fill in G-Matrix
     342 [ +  - ][ +  - ]:     375133 :   setY (NODE_C, NODE_C, +gd); setY (NODE_A, NODE_A, +gd);
     343 [ +  - ][ +  - ]:     375133 :   setY (NODE_C, NODE_A, -gd); setY (NODE_A, NODE_C, -gd);
     344                 :     375133 : }
     345                 :            : 
     346                 :            : // Saves operating points (voltages).
     347                 :     282461 : void diode::saveOperatingPoints (void) {
     348 [ +  - ][ +  - ]:     282461 :   nr_double_t Vd = real (getV (NODE_A) - getV (NODE_C));
     349                 :     282461 :   setOperatingPoint ("Vd", Vd);
     350                 :     282461 : }
     351                 :            : 
     352                 :            : // Loads operating points (voltages).
     353                 :     270361 : void diode::loadOperatingPoints (void) {
     354                 :     270361 :   Ud = getOperatingPoint ("Vd");
     355                 :     270361 : }
     356                 :            : 
     357                 :            : // Calculates and saves operating points.
     358                 :     270361 : void diode::calcOperatingPoints (void) {
     359                 :            : 
     360                 :            :   // load operating points
     361                 :     270361 :   loadOperatingPoints ();
     362                 :            : 
     363                 :            :   // get necessary properties
     364                 :     270361 :   nr_double_t M   = getScaledProperty ("M");
     365                 :     270361 :   nr_double_t Cj0 = getScaledProperty ("Cj0");
     366                 :     270361 :   nr_double_t Vj  = getScaledProperty ("Vj");
     367                 :     270361 :   nr_double_t Fc  = getPropertyDouble ("Fc");
     368                 :     270361 :   nr_double_t Cp  = getPropertyDouble ("Cp");
     369                 :     270361 :   nr_double_t Tt  = getScaledProperty ("Tt");
     370                 :            : 
     371                 :            :   // calculate capacitances and charges
     372                 :            :   nr_double_t Cd;
     373                 :     270361 :   Cd = pnCapacitance (Ud, Cj0, Vj, M, Fc) + Tt * gd + Cp;
     374                 :     270361 :   Qd = pnCharge (Ud, Cj0, Vj, M, Fc) + Tt * Id + Cp * Ud;
     375                 :            : 
     376                 :            :   // save operating points
     377                 :     270361 :   setOperatingPoint ("gd", gd);
     378                 :     270361 :   setOperatingPoint ("Id", Id);
     379                 :     270361 :   setOperatingPoint ("Cd", Cd);
     380                 :     270361 : }
     381                 :            : 
     382                 :            : // Callback for initializing the AC analysis.
     383                 :          2 : void diode::initAC (void) {
     384                 :          2 :   allocMatrixMNA ();
     385                 :          2 : }
     386                 :            : 
     387                 :            : // Callback for the AC analysis.
     388                 :        200 : void diode::calcAC (nr_double_t frequency) {
     389         [ +  - ]:        200 :   nr_double_t gd = getOperatingPoint ("gd");
     390         [ +  - ]:        200 :   nr_double_t Cd = getOperatingPoint ("Cd");
     391                 :        200 :   nr_complex_t y = nr_complex_t (gd, Cd * 2.0 * M_PI * frequency);
     392 [ +  - ][ +  - ]:        200 :   setY (NODE_C, NODE_C, +y); setY (NODE_A, NODE_A, +y);
     393 [ +  - ][ +  - ]:        200 :   setY (NODE_C, NODE_A, -y); setY (NODE_A, NODE_C, -y);
     394                 :        200 : }
     395                 :            : 
     396                 :            : // Callback for the AC noise analysis.
     397                 :          0 : void diode::calcNoiseAC (nr_double_t frequency) {
     398         [ #  # ]:          0 :   setMatrixN (calcMatrixCy (frequency));
     399                 :          0 : }
     400                 :            : 
     401                 :            : #define qState 0 // charge state
     402                 :            : #define cState 1 // current state
     403                 :            : 
     404                 :            : // Callback for initializing the TR analysis.
     405                 :         24 : void diode::initTR (void) {
     406                 :         24 :   setStates (2);
     407                 :         24 :   initDC ();
     408                 :         24 : }
     409                 :            : 
     410                 :            : // Callback for the TR analysis.
     411                 :     270181 : void diode::calcTR (nr_double_t) {
     412                 :     270181 :   calcDC ();
     413                 :     270181 :   saveOperatingPoints ();
     414                 :     270181 :   calcOperatingPoints ();
     415                 :            : 
     416                 :     270181 :   nr_double_t Cd = getOperatingPoint ("Cd");
     417                 :            : 
     418                 :     270181 :   transientCapacitance (qState, NODE_A, NODE_C, Cd, Ud, Qd);
     419                 :     270181 : }
     420                 :            : 
     421                 :            : // Callback for initializing the HB analysis.
     422                 :          1 : void diode::initHB (int frequencies) {
     423                 :          1 :   deviceStates (StateVars, frequencies);
     424                 :          1 :   doHB = true;
     425                 :          1 :   prepareDC ();
     426                 :          1 :   allocMatrixHB ();
     427                 :          1 : }
     428                 :            : 
     429                 :            : // Callback for the HB analysis.
     430                 :        176 : void diode::calcHB (int frequency) {
     431                 :            :   // set current frequency state
     432                 :        176 :   deviceState (frequency);
     433                 :            : 
     434                 :            :   // g's (dI/dU) into Y-Matrix and I's into I-Vector
     435                 :        176 :   calcDC ();
     436                 :            : 
     437                 :            :   // calculate Q and C
     438                 :        176 :   saveOperatingPoints ();
     439                 :        176 :   calcOperatingPoints ();
     440                 :            : 
     441                 :        176 :   nr_double_t Cd = getOperatingPoint ("Cd");
     442                 :            : 
     443                 :            :   // fill in Q's in Q-Vector
     444         [ +  - ]:        176 :   setQ (NODE_C, +Qd);
     445         [ +  - ]:        176 :   setQ (NODE_A, -Qd);
     446                 :            : 
     447         [ +  - ]:        176 :   setCV (NODE_C, -Cd * Ud);
     448         [ +  - ]:        176 :   setCV (NODE_A, +Cd * Ud);
     449                 :            : 
     450                 :            :   // fill in C's (dQ/dU) into QV-Matrix
     451 [ +  - ][ +  - ]:        176 :   setQV (NODE_C, NODE_C, +Cd); setQV (NODE_A, NODE_A, +Cd);
     452 [ +  - ][ +  - ]:        176 :   setQV (NODE_C, NODE_A, -Cd); setQV (NODE_A, NODE_C, -Cd);
     453                 :        176 : }
     454                 :            : 
     455                 :            : // properties
     456                 :            : PROP_REQ [] = {
     457                 :            :   { "Is", PROP_REAL, { 1e-15, PROP_NO_STR }, PROP_POS_RANGE },
     458                 :            :   { "N", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1e-6, 100) },
     459                 :            :   { "M", PROP_REAL, { 0.5, PROP_NO_STR }, PROP_RNGII (0, 2) },
     460                 :            :   { "Cj0", PROP_REAL, { 10e-15, PROP_NO_STR }, PROP_POS_RANGE },
     461                 :            :   { "Vj", PROP_REAL, { 0.7, PROP_NO_STR }, PROP_RNGXI (0, 10) },
     462                 :            :   PROP_NO_PROP };
     463                 :            : PROP_OPT [] = {
     464                 :            :   { "Rs", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     465                 :            :   { "Isr", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     466                 :            :   { "Nr", PROP_REAL, { 2, PROP_NO_STR }, PROP_RNGII (0.1, 100) },
     467                 :            :   { "Bv", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     468                 :            :   { "Ibv", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
     469                 :            :   { "Ikf", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     470                 :            :   { "Tt", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     471                 :            :   { "Fc", PROP_REAL, { 0.5, PROP_NO_STR }, PROP_RNGIX (0, 1) },
     472                 :            :   { "Cp", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     473                 :            :   { "Kf", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     474                 :            :   { "Af", PROP_REAL, { 1, PROP_NO_STR }, PROP_POS_RANGE },
     475                 :            :   { "Ffe", PROP_REAL, { 1, PROP_NO_STR }, PROP_POS_RANGE },
     476                 :            :   { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
     477                 :            :   { "Xti", PROP_REAL, { 3, PROP_NO_STR }, PROP_POS_RANGE },
     478                 :            :   { "Eg", PROP_REAL, { EgSi, PROP_NO_STR }, PROP_POS_RANGE },
     479                 :            :   { "Tbv", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     480                 :            :   { "Trs", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
     481                 :            :   { "Ttt1", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
     482                 :            :   { "Ttt2", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
     483                 :            :   { "Tm1", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
     484                 :            :   { "Tm2", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
     485                 :            :   { "Tnom", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
     486                 :            :   { "Area", PROP_REAL, { 1, PROP_NO_STR }, PROP_POS_RANGEX },
     487                 :            :   PROP_NO_PROP };
     488                 :            : struct define_t diode::cirdef =
     489                 :            :   { "Diode", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_NONLINEAR, PROP_DEF };

Generated by: LCOV version 1.11