/*************************************************************************** * Copyright (C) 2003-2004 by David Saxton * * david@bluehaze.org * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "bjt.h" #include "circuit.h" #include "elementset.h" #include "element.h" #include "logic.h" #include "matrix.h" #include "nonlinear.h" #include "vec.h" #include #include #include #include ElementSet::ElementSet( Circuit * circuit, const int n, const int m ) { m_pCircuit = circuit; m_cn = n; m_cb = m; p_logicIn = 0l; p_A = new Matrix( m_cn, m_cb ); p_b = new Vector(m_cn+m_cb); p_x = new Vector(m_cn+m_cb); p_x_prev = new Vector(m_cn+m_cb); m_cbranches = new CBranch*[m_cb]; m_cnodes = new CNode*[m_cn]; for ( uint i=0; iset_n(i); } for ( uint i=0; iset_n(i); } m_ground = new CNode(); m_ground->isGround = true; b_containsNonLinear = false; } ElementSet::~ElementSet() { const ElementList::iterator end = m_elementList.end(); for ( ElementList::iterator it = m_elementList.begin(); it != end; ++it ) { // Note: By calling setElementSet(0l), we might have deleted it (the Element will commit // suicide when both the the ElementSet and Component to which it belongs have deleted // themselves). So be very careful it you plan to do anything with the (*it) pointer if (*it) (*it)->elementSetDeleted(); } for ( uint i=0; isetCacheInvalidated(); } void ElementSet::addElement( Element *e ) { if ( !e || m_elementList.contains(e) ) return; e->setElementSet(this); m_elementList.append(e); if ( e->isNonLinear() ) { b_containsNonLinear = true; m_cnonLinearList.append( static_cast(e) ); } } void ElementSet::createMatrixMap() { p_A->createMap(); // And do our logic as well... m_clogic = 0; ElementList::iterator end = m_elementList.end(); for ( ElementList::iterator it = m_elementList.begin(); it != end; ++it ) { if ( dynamic_cast(*it) ) m_clogic++; } p_logicIn = new LogicIn*[m_clogic]; int i=0; for ( ElementList::iterator it = m_elementList.begin(); it != end; ++it ) { if ( LogicIn * in = dynamic_cast(*it) ) p_logicIn[i++] = in; } } void ElementSet::doNonLinear( int maxIterations, double maxErrorV, double maxErrorI ) { // p_x_prev->reset(); // And now tell the cnodes and cbranches about their new voltages & currents updateInfo(); const NonLinearList::iterator end = m_cnonLinearList.end(); int k = 0; do { // Tell the nonlinear elements to update its J, A and b from the newly calculated x for ( NonLinearList::iterator it = m_cnonLinearList.begin(); it != end; ++it ) (*it)->update_dc(); *p_x = *p_b; p_A->performLU(); p_A->fbSub(p_x); updateInfo(); // Now, check for convergence bool converged = true; for ( unsigned i = 0; i < m_cn; ++i ) { double diff = std::abs( (*p_x_prev)[i] - (*p_x)[i] ); if ( diff > maxErrorI ) { converged = false; break; } } if ( converged ) { for ( unsigned i = m_cn; i < m_cn+m_cb; ++i ) { double diff = std::abs( (*p_x_prev)[i] - (*p_x)[i] ); if ( diff > maxErrorV ) { converged = false; break; } } } *p_x_prev = *p_x; if ( converged ) break; } while ( ++k < maxIterations ); } bool ElementSet::doLinear( bool performLU ) { if ( b_containsNonLinear || (!p_b->isChanged() && ((performLU && !p_A->isChanged()) || !performLU)) ) return false; if (performLU) p_A->performLU(); *p_x = *p_b; p_A->fbSub(p_x); updateInfo(); p_b->setUnchanged(); return true; } void ElementSet::updateInfo() { for ( uint i=0; iv = v; } else { (*p_x)[i] = 0.; m_cnodes[i]->v = 0.; } } for ( uint i=0; ii = I; } else { (*p_x)[i+m_cn] = 0.; m_cbranches[i]->i = 0.; } } // Tell logic to check themselves for ( uint i=0; icheck(); } } void ElementSet::displayEquations() { std::cout.setf(std::ios_base::fixed); std::cout.precision(5); std::cout.setf(std::ios_base::showpoint); std::cout << "A x = b :"<g(i,j); // if ( value > 0 ) cout <<"+"; // else if ( value == 0 ) cout <<" "; std::cout.width(10); std::cout << value<<" "; } std::cout << ") ( "<<(*p_x)[i]<<" ) = ( "; std::cout<<(*p_b)[i]<<" )"<displayLU(); }