00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "bjt.h"
00012 #include "circuit.h"
00013 #include "elementset.h"
00014 #include "element.h"
00015 #include "logic.h"
00016 #include "matrix.h"
00017 #include "nonlinear.h"
00018
00019 #include <kdebug.h>
00020
00021 #include <cmath>
00022 #include <iostream>
00023 #include <cassert>
00024
00025 ElementSet::ElementSet(Circuit *circuit, const int n, const int m )
00026 : p_logicIn(0), m_pCircuit(circuit)
00027 {
00028
00029 int matsize = m + n;
00030 if(matsize) {
00031 p_A = new Matrix(n, matsize);
00032 p_b = new QuickVector(matsize);
00033 p_x = new QuickVector(matsize);
00034 } else {
00035 p_A = 0;
00036 p_x = p_b = 0;
00037 }
00038
00039 m_cn = n;
00040 m_cnodes = new CNode*[m_cn];
00041 for( uint i=0; i<m_cn; i++ ) {
00042 m_cnodes[i] = new CNode(i);
00043 }
00044
00045
00046
00047 m_cb = m;
00048 m_cbranches = new CBranch*[m_cb];
00049 for( uint i=0; i<m_cb; i++ ) {
00050 m_cbranches[i] = new CBranch(i);
00051 }
00052
00053 m_ground = new CNode();
00054 m_ground->isGround = true;
00055
00056 b_containsNonLinear = false;
00057 }
00058
00059 ElementSet::~ElementSet()
00060 {
00061 const ElementList::iterator end = m_elementList.end();
00062 for( ElementList::iterator it = m_elementList.begin(); it != end; ++it ) {
00063
00064
00065
00066 if(*it) (*it)->elementSetDeleted();
00067 }
00068
00069 for( uint i=0; i<m_cn; i++ ) {
00070 delete m_cnodes[i];
00071 }
00072 delete[] m_cnodes;
00073
00074
00076 for( uint i=0; i<m_cb; i++ ) {
00077 delete m_cbranches[i];
00078 }
00079 delete[] m_cbranches;
00081
00082 delete[] p_logicIn;
00083
00084 delete m_ground;
00085 if(p_A) delete p_A;
00086 if(p_b) delete p_b;
00087 if(p_x) delete p_x;
00088 }
00089
00090 void ElementSet::setCacheInvalidated()
00091 {
00092 m_pCircuit->setCacheInvalidated();
00093 }
00094
00095 void ElementSet::addElement( Element *e )
00096 {
00097 if(!e || m_elementList.contains(e)) return;
00098 e->setElementSet(this);
00099 m_elementList.append(e);
00100
00101 if(e->isNonLinear()) {
00102 b_containsNonLinear = true;
00103 m_cnonLinearList.append(static_cast<NonLinear*>(e));
00104 }
00105 }
00106
00107 void ElementSet::createMatrixMap()
00108 {
00109 p_A->createMap();
00110
00111
00112 m_clogic = 0;
00113 ElementList::iterator end = m_elementList.end();
00114 for(ElementList::iterator it = m_elementList.begin(); it != end; ++it) {
00115 if(dynamic_cast<LogicIn*>(*it)) m_clogic++;
00116 }
00117
00118 p_logicIn = new LogicIn*[m_clogic];
00119 int i=0;
00120 for(ElementList::iterator it = m_elementList.begin(); it != end; ++it) {
00121 if(LogicIn *in = dynamic_cast<LogicIn*>(*it)) p_logicIn[i++] = in;
00122 }
00123 }
00124
00125
00126
00127 void ElementSet::doNonLinear( int maxIterations, double maxErrorV, double maxErrorI )
00128 {
00129
00130 updateInfo();
00131 const NonLinearList::iterator end = m_cnonLinearList.end();
00132 QuickVector *p_x_prev = 0;
00133 int k = 0;
00134 bool converged;
00135 do {
00136
00137 for( NonLinearList::iterator it = m_cnonLinearList.begin(); it != end; ++it )
00138 (*it)->update_dc();
00139
00140
00141 delete p_x;
00142 p_x = new QuickVector(p_b);
00143
00144 p_A->performLU();
00145 p_A->fbSub(p_x);
00146
00147 #ifdef CHECK
00148 {
00149 QuickVector *result = new QuickVector(p_x->size());
00150 p_A->multiply(p_x,result);
00151 QuickVector *error = *p_b - result;
00152 delete result;
00153 const unsigned int end = error->size();
00154 double sum = 0;
00155 for(unsigned int i = 0; i < end; i++) {
00156 sum += fabs((*error)[i]);
00157 }
00158 delete error;
00159 assert(sum < EPSILON);
00160 }
00161 #endif
00162 updateInfo();
00163
00164 if(p_x_prev) {
00165
00166
00167
00168 double sum = 0;
00169 for( unsigned i = 0; i < m_cn+m_cb; ++i ) {
00170 sum += fabs( (*p_x_prev)[i] - (*p_x)[i]);
00171 }
00172
00173 converged = (sum < EPSILON);
00174 delete p_x_prev;
00175 } else converged = false;
00176
00177 p_x_prev = new QuickVector(p_x);
00178
00179 } while(!converged && (++k < maxIterations));
00180
00181 if(p_x_prev) delete p_x_prev;
00182 }
00183
00184
00185
00186 bool ElementSet::doLinear(bool performLU) {
00187 if( b_containsNonLinear || (!p_b->isChanged() && ((performLU && !p_A->isChanged()) || !performLU)) ) return false;
00188
00189 if(performLU) p_A->performLU();
00190
00191
00192 delete p_x;
00193 p_x = new QuickVector(p_b);
00194
00195 p_A->fbSub(p_x);
00196
00197 #ifdef CHECK
00198 {QuickVector *result = new QuickVector(p_x->size());
00199 p_A->multiply(p_x,result);
00200 QuickVector *error = *p_b - result;
00201 delete result;
00202 const unsigned int end = error->size();
00203 double sum = 0;
00204 for(unsigned int i = 0; i < end; i++)
00205 sum += fabs((*error)[i]);
00206 delete error;
00207 kdDebug() << sum << endl;
00208 assert(sum < EPSILON);}
00209 #endif
00210
00211 updateInfo();
00212 p_b->setUnchanged();
00213
00214 return true;
00215 }
00216
00217 void ElementSet::updateInfo()
00218 {
00219 for(uint i=0; i<m_cn; i++) {
00220 const double v = (*p_x)[i];
00221 if(std::isfinite(v)) {
00222 m_cnodes[i]->v = v;
00223 } else {
00224 (*p_x)[i] = 0.;
00225 m_cnodes[i]->v = 0.;
00226 }
00227 }
00228
00229 for( uint i=0; i<m_cb; i++ ) {
00230
00231 const double I = (*p_x)[i+m_cn];
00232 if(std::isfinite(I)) {
00233 m_cbranches[i]->i = I;
00234 } else {
00235 (*p_x)[i+m_cn] = 0.;
00236 m_cbranches[i]->i = 0.;
00237 }
00238 }
00239
00240
00241 for( uint i=0; i<m_clogic; ++i ) {
00242 p_logicIn[i]->check();
00243 }
00244 }
00245
00246 void ElementSet::displayEquations()
00247 {
00248 std::cout.setf(std::ios_base::fixed);
00249 std::cout.precision(5);
00250 std::cout.setf(std::ios_base::showpoint);
00251 std::cout << "A x = b :"<<std::endl;
00252 for(uint i=0; i<m_cn+m_cb; i++ ) {
00253 std::cout << "( ";
00254 for( uint j=0; j<m_cn+m_cb; j++ ) {
00255 const double value = p_A->g(i,j);
00256
00257
00258 std::cout.width(10);
00259 std::cout << value<<" ";
00260 }
00261 std::cout << ") ( "<<(*p_x)[i]<<" ) = ( ";
00262 std::cout<<(*p_b)[i]<<" )"<<std::endl;
00263 }
00264 std::cout << "A_LU:"<<std::endl;
00265 p_A->displayLU();
00266 }
00267