Logo Search packages:      
Sourcecode: ktechlab version File versions  Download package

elementset.cpp

/***************************************************************************
 *   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 <kdebug.h>

#include <cmath>
#include <iostream>
#include <assert.h>

00026 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; i<m_cn; i++ )
      {
            m_cnodes[i] = new CNode();
            m_cnodes[i]->set_n(i);
      }
      for ( uint i=0; i<m_cb; i++ )
      {
            m_cbranches[i] = new CBranch();
            m_cbranches[i]->set_n(i);
      }
      m_ground = new CNode();
      m_ground->isGround = true;
      b_containsNonLinear = false;
}

00053 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; i<m_cn; i++ )
      {
            delete m_cnodes[i];
      }
      for ( uint i=0; i<m_cb; i++ )
      {
            delete m_cbranches[i];
      }
      delete[] m_cbranches;
      delete[] m_cnodes;
      delete[] p_logicIn;
      delete m_ground;
      delete p_A;
      delete p_b;
      delete p_x;
      delete p_x_prev;
}


void ElementSet::setCacheInvalidated()
{
      m_pCircuit->setCacheInvalidated();
}


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<NonLinear*>(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<LogicIn*>(*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<LogicIn*>(*it) )
                  p_logicIn[i++] = in;
      }
}


00126 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 );
}


00180 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;
}


00197 void ElementSet::updateInfo()
{
      for ( uint i=0; i<m_cn; i++ )
      {
            const double v = (*p_x)[i];
            if (std::isfinite(v)) {
                  m_cnodes[i]->v = v;
            } else {
                  (*p_x)[i] = 0.;
                  m_cnodes[i]->v = 0.;
            }
      }
      for ( uint i=0; i<m_cb; i++ )
      {
            // NOTE: I've used lowercase and uppercase "I" here, so be careful!
            const double I = (*p_x)[i+m_cn];
            if (std::isfinite(I)) {
                  m_cbranches[i]->i = I;
            } else {
                  (*p_x)[i+m_cn] = 0.;
                  m_cbranches[i]->i = 0.;
            }
      }
      
      // Tell logic to check themselves
      for ( uint i=0; i<m_clogic; ++i )
      {
            p_logicIn[i]->check();
      }
}


00229 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 :"<<std::endl;
      for ( uint i=0; i<m_cn+m_cb; i++ )
      {
            std::cout << "( ";
            for ( uint j=0; j<m_cn+m_cb; j++ )
            {
                  const double value = p_A->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]<<" )"<<std::endl;
      }
      std::cout << "A_LU:"<<std::endl;
      p_A->displayLU();
}



Generated by  Doxygen 1.6.0   Back to index