From 5de3dd4762ca33a0f92e79ffa4fe2ff67069d531 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 24 Feb 2010 01:49:02 +0000 Subject: Added KDE3 version of ktechlab git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/ktechlab@1095338 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- src/electronics/simulation/elementset.cpp | 253 ++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 src/electronics/simulation/elementset.cpp (limited to 'src/electronics/simulation/elementset.cpp') diff --git a/src/electronics/simulation/elementset.cpp b/src/electronics/simulation/elementset.cpp new file mode 100644 index 0000000..25057c2 --- /dev/null +++ b/src/electronics/simulation/elementset.cpp @@ -0,0 +1,253 @@ +/*************************************************************************** + * 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(); +} + + -- cgit v1.2.3