00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <vector>
00012 #include "diode.h"
00013 #include "elementset.h"
00014 #include "matrix.h"
00015
00016 #include <cmath>
00017
00018
00019
00020 DiodeSettings::DiodeSettings()
00021 {
00022 reset();
00023 }
00024
00025 void DiodeSettings::reset()
00026 {
00027 I_S = 1e-15;
00028 N = 1.0;
00029 V_B = 4.7;
00030 }
00031
00032
00033
00034 Diode::Diode()
00035 : NonLinear()
00036 {
00037 m_numCNodes = 2;
00038 g_new = g_old = I_new = I_old = V_prev = 0.0;
00039 }
00040
00041 Diode::~Diode()
00042 {
00043 }
00044
00045 void Diode::add_map()
00046 {
00047 if (!b_status) return;
00048
00049 if ( !p_cnode[0]->isGround ) {
00050 p_A->setUse( p_cnode[0]->n(), p_cnode[0]->n(), Map::et_unstable, false );
00051 }
00052
00053 if ( !p_cnode[1]->isGround ) {
00054 p_A->setUse( p_cnode[1]->n(), p_cnode[1]->n(), Map::et_unstable, false );
00055 }
00056
00057 if ( !p_cnode[0]->isGround && !p_cnode[1]->isGround ) {
00058 p_A->setUse( p_cnode[0]->n(), p_cnode[1]->n(), Map::et_unstable, false );
00059 p_A->setUse( p_cnode[1]->n(), p_cnode[0]->n(), Map::et_unstable, false );
00060 }
00061 }
00062
00063 void Diode::add_initial_dc()
00064 {
00065 g_new = g_old = I_new = I_old = V_prev = 0.0;
00066 update_dc();
00067 }
00068
00069 double Diode::current() const
00070 {
00071 if (!b_status) return 0.0;
00072
00073 double I;
00074 calcIg(p_cnode[0]->v - p_cnode[1]->v, &I, 0);
00075
00076 return I;
00077 }
00078
00079 void Diode::updateCurrents()
00080 {
00081 if (!b_status) return;
00082
00083 m_cnodeI[1] = current();
00084 m_cnodeI[0] = -m_cnodeI[1];
00085 }
00086
00087 void Diode::update_dc()
00088 {
00089 if (!b_status) return;
00090
00091 calc_eq();
00092
00093 A_g( 0, 0 ) += g_new - g_old;
00094 A_g( 1, 1 ) += g_new - g_old;
00095 A_g( 0, 1 ) -= g_new - g_old;
00096 A_g( 1, 0 ) -= g_new - g_old;
00097
00098 b_i( 0 ) -= I_new - I_old;
00099 b_i( 1 ) += I_new - I_old;
00100
00101 g_old = g_new;
00102 I_old = I_new;
00103 }
00104
00105 #ifndef MIN
00106 # define MIN(x,y) (((x) < (y)) ? (x) : (y))
00107 #endif
00108
00109 void Diode::calc_eq()
00110 {
00111 double I_S = m_diodeSettings.I_S;
00112 double N = m_diodeSettings.N;
00113 double V_B = m_diodeSettings.V_B;
00114
00115 double v = p_cnode[0]->v - p_cnode[1]->v;
00116
00117
00118 double V_crit = diodeCriticalVoltage( I_S, N * V_T );
00119 if (V_B != 0 && v < MIN (0, -V_B + 10 * N * V_T)) {
00120 double V = -(v + V_B);
00121 V = diodeVoltage( V, -(V_prev + V_B), V_T * N, V_crit );
00122 v = -(V + V_B);
00123 } else v = diodeVoltage( v, V_prev, V_T * N, V_crit );
00124
00125 V_prev = v;
00126
00127 double I_D;
00128 calcIg( v, & I_D, & g_new );
00129
00130 I_new = I_D - (v * g_new);
00131 }
00132
00133 void Diode::calcIg(double V, double *I_D, double *g) const
00134 {
00135 double I_S = m_diodeSettings.I_S;
00136 double N = m_diodeSettings.N;
00137 double V_B = m_diodeSettings.V_B;
00138
00139 double gtiny = (V < - 10 * V_T * N && V_B != 0) ? I_S : 0;
00140
00141 if ( V >= (-3 * N * V_T) ) {
00142 if(g) *g = diodeConductance( V, I_S, V_T * N ) + gtiny;
00143 *I_D = diodeCurrent( V, I_S, V_T * N ) + (gtiny * V);
00144 } else if ( V_B == 0 || V >= -V_B ) {
00145 double a = (3 * N * V_T) / (V * M_E);
00146 a = a * a * a;
00147 *I_D = (-I_S * (1 + a)) + (gtiny * V);
00148 if ( g ) *g = ((I_S * 3 * a) / V) + gtiny;
00149 } else {
00150 double a = exp( -(V_B + V) / N / V_T );
00151 *I_D = (-I_S * a) + (gtiny * V);
00152 if ( g ) *g = I_S * a / V_T / N + gtiny;
00153 }
00154 }
00155
00156 void Diode::setDiodeSettings( const DiodeSettings & settings )
00157 {
00158 m_diodeSettings = settings;
00159 if (p_eSet) p_eSet->setCacheInvalidated();
00160 }
00161
00162
00163