File indexing completed on 2024-05-05 05:46:10
0001 /*************************************************************************** 0002 * Copyright (C) 2003-2004 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "diode.h" 0012 #include "elementset.h" 0013 0014 #include <algorithm> 0015 #include <vector> 0016 0017 #include <cmath> 0018 0019 // BEGIN class Diode Settings 0020 DiodeSettings::DiodeSettings() 0021 { 0022 reset(); 0023 } 0024 0025 void DiodeSettings::reset() 0026 { 0027 I_S = 1e-15; 0028 N = 1.0; 0029 V_B = 4.7; 0030 // R = 0.001; 0031 } 0032 // END class Diode Settings 0033 0034 // BEGIN class Diode 0035 Diode::Diode() 0036 : NonLinear() 0037 { 0038 m_numCNodes = 2; 0039 g_new = g_old = I_new = I_old = V_prev = 0.0; 0040 updateLim(); 0041 } 0042 0043 Diode::~Diode() 0044 { 0045 } 0046 0047 void Diode::add_initial_dc() 0048 { 0049 g_new = g_old = I_new = I_old = V_prev = 0.0; 0050 update_dc(); 0051 } 0052 0053 double Diode::current() const 0054 { 0055 if (!b_status) 0056 return 0.0; 0057 0058 double I; 0059 calcIg(p_cnode[0]->v - p_cnode[1]->v, &I, nullptr); 0060 0061 return I; 0062 } 0063 0064 void Diode::updateCurrents() 0065 { 0066 if (!b_status) 0067 return; 0068 0069 m_cnodeI[1] = current(); 0070 m_cnodeI[0] = -m_cnodeI[1]; 0071 } 0072 0073 void Diode::update_dc() 0074 { 0075 if (!b_status) 0076 return; 0077 0078 calc_eq(); 0079 0080 A_g(0, 0) += g_new - g_old; 0081 A_g(1, 1) += g_new - g_old; 0082 A_g(0, 1) -= g_new - g_old; 0083 A_g(1, 0) -= g_new - g_old; 0084 0085 b_i(0) -= I_new - I_old; 0086 b_i(1) += I_new - I_old; 0087 0088 g_old = g_new; 0089 I_old = I_new; 0090 } 0091 0092 void Diode::calc_eq() 0093 { 0094 double N = m_diodeSettings.N; 0095 double V_B = m_diodeSettings.V_B; 0096 // double R = m_diodeSettings.R; 0097 0098 double v = p_cnode[0]->v - p_cnode[1]->v; 0099 0100 // adjust voltage to help convergence 0101 if (V_B != 0 && v < std::min<double>(0, -V_B + 10 * N)) { 0102 double V = -(v + V_B); 0103 V = diodeVoltage(V, -(V_prev + V_B), N, V_lim); 0104 v = -(V + V_B); 0105 } else 0106 v = diodeVoltage(v, V_prev, N, V_lim); 0107 0108 V_prev = v; 0109 0110 double I_D; 0111 calcIg(v, &I_D, &g_new); 0112 0113 I_new = I_D - (v * g_new); 0114 } 0115 0116 void Diode::calcIg(double V, double *I_D, double *g) const 0117 { 0118 double I_S = m_diodeSettings.I_S; 0119 double N = m_diodeSettings.N; 0120 double V_B = m_diodeSettings.V_B; 0121 // double R = m_diodeSettings.R; 0122 0123 double g_tiny = (V < -10 * V_T * N && V_B != 0) ? I_S : 0; 0124 0125 if (V >= (-3 * N * V_T)) { 0126 if (g) 0127 *g = diodeConductance(V, I_S, N) + g_tiny; 0128 *I_D = diodeCurrent(V, I_S, N) + (g_tiny * V); 0129 } else if (V_B == 0 || V >= -V_B) { 0130 double a = (3 * N * V_T) / (V * M_E); 0131 a = a * a * a; 0132 *I_D = (-I_S * (1 + a)) + (g_tiny * V); 0133 if (g) 0134 *g = ((I_S * 3 * a) / V) + g_tiny; 0135 } else { 0136 double a = exp(-(V_B + V) / N / V_T); 0137 *I_D = (-I_S * a) + (g_tiny * V); 0138 if (g) 0139 *g = I_S * a / V_T / N + g_tiny; 0140 } 0141 } 0142 0143 void Diode::setDiodeSettings(const DiodeSettings &settings) 0144 { 0145 m_diodeSettings = settings; 0146 updateLim(); 0147 if (p_eSet) 0148 p_eSet->setCacheInvalidated(); 0149 } 0150 0151 void Diode::updateLim() 0152 { 0153 double I_S = m_diodeSettings.I_S; 0154 double N = m_diodeSettings.N; 0155 V_lim = diodeLimitedVoltage(I_S, N); 0156 } 0157 // END class Diode