/******************************************************* * * DESCRIPTION: Electrical circuit and components classes * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include "circuit.h" /******************************************************************* * Defaults initialization *******************************************************************/ const RealValue Resistance::DefaultR = DEFAULT_RESISTANCE; const RealValue Capacitor::DefaultC = DEFAULT_CAPACITANCE; const RealValue Capacitor::DefaultInitialLoad = 0; const RealValue Inductor::DefaultI = DEFAULT_INDUCTANCE; const RealValue Inductor::DefaultInitialLoad = 0; const RealValue Transformer::DefaultTR = DEFAULT_TR; const RealValue Gyrator::DefaultGC = DEFAULT_GC; //****************************************************** // // Class OnePort // //****************************************************** /******************************************************************* * Function Name: *******************************************************************/ OnePort::OnePort( const Id &pid ) :PortComp( pid ) { port.p.id = "p"; port.p.type = PositivePin; port.n.id = "n"; port.n.type = NegativePin; } /******************************************************************* * Function Name: *******************************************************************/ Pin OnePort::pin( const pId& pid ) const { if( !validPin( pid ) ) { throw OnePortException( INVALID_PIN_INDEX_MSG ); } return ( port.p.id == pid ? port.p : port.n ); } /******************************************************************* * Function Name: *******************************************************************/ Pin *OnePort::getPins() { Pin *pins = new Pin [2]; assert( pins ); pins[0] = port.p; pins[1] = port.n; return pins; } /******************************************************************* * Function Name: *******************************************************************/ Port OnePort::getPort( const int index ) const { if( index != 1 ) { throw OnePortException( INVALID_PORT_INDEX_MSG ); } return port; } /******************************************************************* * Function Name: *******************************************************************/ pId OnePort::accessPortPin( const PinType &pType, const int index ) const { if( index != 1 ) { throw OnePortException( INVALID_PIN_INDEX_MSG ); } return ( pType == PositivePin ? accessPin( port.p.id ) : accessPin( port.n.id ) ); } //****************************************************** // // Class TwoPort // //****************************************************** /******************************************************************* * Function Name: *******************************************************************/ TwoPort::TwoPort( const Id &pid ) :PortComp( pid ) { port1.p.id = "p1"; port1.p.type = PositivePin; port1.n.id = "n1"; port1.n.type = NegativePin; port2.p.id = "p2"; port2.p.type = PositivePin; port2.n.id = "n2"; port2.n.type = NegativePin; } /******************************************************************* * Function Name: *******************************************************************/ Pin TwoPort::pin( const pId& pid ) const { if( !validPin( pid ) ) { throw TwoPortException( INVALID_PIN_ID_MSG ); } if( port1.p.id == pid ) return port1.p; else if( port1.n.id == pid ) return port1.n; else if( port2.p.id == pid ) return port2.p; else if( port2.n.id == pid ) return port2.n; throw TwoPortException( INVALID_PIN_ID_MSG ); } /******************************************************************* * Function Name: *******************************************************************/ Pin *TwoPort::getPins() { Pin *pins = new Pin [4]; assert( pins ); pins[0] = port1.p; pins[1] = port1.n; pins[2] = port2.p; pins[3] = port2.n; return pins; } /******************************************************************* * Function Name: *******************************************************************/ Port TwoPort::getPort( const int index ) const { if( index < 0 || index > 2 ) { throw TwoPortException( INVALID_PORT_INDEX_MSG ); } return ( index == 1 ? port1 : port2 ); } /******************************************************************* * Function Name: *******************************************************************/ pId TwoPort::accessPortPin( const PinType &pType, const int index ) const { if( index < 0 || index > 2 ) { throw TwoPortException( INVALID_PORT_INDEX_MSG ); } if ( index == 1 ) return ( pType == PositivePin ? accessPin( port1.p.id ) : accessPin( port1.n.id ) ); else return ( pType == PositivePin ? accessPin( port2.p.id ) : accessPin( port2.n.id ) ); } //****************************************************** // // Class Ground // //****************************************************** /******************************************************************* * Function Name: *******************************************************************/ Ground::Ground( const Id &id ) :EComp( id ) { _pin.id = "p"; _pin.type = PositivePin; } /******************************************************************* * Function Name: *******************************************************************/ Pin Ground::pin( const pId& pid ) const { if( !validPin( pid ) ) { throw ECompException( INVALID_OPERATION_TYPE_MSG ); } return _pin; } /******************************************************************* * Function Name: *******************************************************************/ Pin *Ground::getPins() { Pin *pins = new Pin [1]; assert( pins ); pins[0] = _pin; return pins; } //****************************************************** // // Class ECircuit // //****************************************************** /******************************************************************* * Function Name: *******************************************************************/ ECircuit::ECircuit( const string &aid ) { id = aid; graph = new CircuitGraph(); assert( graph != NULL ); comps = new EComps(); assert( comps != NULL ); } /******************************************************************* * Function Name: *******************************************************************/ ECircuit::~ECircuit() { if( graph ) delete graph; EComps::iterator cursor; for ( cursor = comps->begin(); cursor != comps->end(); cursor++ ) { if( cursor->second ) delete ( cursor->second ); } if( comps ) delete comps; sources.clear(); grounds.clear(); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::addComponent( EComp *comp ) { if( comp->className() == "Ground" ) return addComponent( (Ground *)comp ); if( comp->className() == "VoltageSource" ) return addComponent( (VoltageSource *)comp ); if( comp->className() == "CurrentSource" ) return addComponent( (CurrentSource *)comp ); return _addComponent( comp ); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::addComponent( VoltageSource *source ) { if( _addComponent( source ) ) { sources.push_back( source ); return true; } return false; } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::addComponent( CurrentSource *source ) { if( _addComponent( source ) ) { sources.push_back( source ); return true; } return false; } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::addComponent( Ground *ground ) { if( _addComponent( ground ) ) { grounds.push_back( ground ); return true; } return false; } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::delComponent( const Id &id ) { EComp *comp; if( !findComponent( id, comp ) ) return false; int n = comp->pins(); Pin *pins = comp->getPins(); for( int i=0; i < n; i++ ) { graph->delNode( comp->accessPin( pins[i].id ) ); } comps->erase( id ); removeSource( comp ); removeGround( comp ); delete (comp); return true; } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::findComponent( const Id &comp, EComp *& pcomp ) { EComps::iterator it; it = comps->find( comp ); pcomp = it->second; return ( it != comps->end() ); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::connect( const Id &comp1, const pId &p1, const Id &comp2, const pId &p2 ) { if( comp1 == comp2 ) throw ECircuitException( CONNECT_SAMECOMP_ERROR_MSG + comp1 ); EComp *c1, *c2; if ( !findComponent( comp1, c1 ) ) throw ECircuitException( CONNECT_NOCOMP_ERROR_MSG + comp1 ); if ( !findComponent( comp2, c2 ) ) throw ECircuitException( CONNECT_NOCOMP_ERROR_MSG + comp2 ); return( connect( *c1, p1, *c2, p2 ) ); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::connect( const EComp &comp1, const pId &p1, const EComp &comp2, const pId &p2 ) { if( comp1.getId() == comp2.getId() ) throw ECircuitException( CONNECT_SAMECOMP_ERROR_MSG + comp1.getId() ); EComp *c1, *c2; if ( !findComponent( comp1.getId(), c1 ) ) throw ECircuitException( CONNECT_NOCOMP_ERROR_MSG + comp1.getId() ); if ( !findComponent( comp2.getId(), c2 ) ) throw ECircuitException( CONNECT_NOCOMP_ERROR_MSG + comp2.getId() ); if( comp1 != *c1 ) return false; if( comp2 != *c2 ) return false; return ( graph->addEdge( comp1.accessPin( p1 ), comp2.accessPin( p2 ) ) ); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::connect( const EComp *comp1, const pId &p1, const EComp *comp2, const pId &p2 ) { if( comp1 == NULL || comp2 == NULL ) return false; EComp *c1, *c2; if ( !findComponent( comp1->getId(), c1 ) ) throw ECircuitException( CONNECT_NOCOMP_ERROR_MSG + comp1->getId() ); if ( !findComponent( comp2->getId(), c2 ) ) throw ECircuitException( CONNECT_NOCOMP_ERROR_MSG + comp2->getId() ); if( comp1 != c1 ) return false; if( comp2 != c2 ) return false; return ( graph->addEdge( comp1->accessPin( p1 ), comp2->accessPin( p2 ) ) ); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::connect( const EComp &comp1, const Pin &p1, const EComp &comp2, const Pin &p2 ) { return connect( comp1, p1.id, comp2, p2.id ); } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::_addComponent( EComp *comp ) { assert( comp != NULL ); EComp *c1; if( findComponent( comp->getId(), c1 ) ) throw ECircuitException( ADD_COMP_ERROR_MSG + comp->getId() ); int n = comp->pins(); Pin *pins = comp->getPins(); for( int i=0; i < n; i++ ) { graph->addNode( comp->accessPin( pins[i].id ) ); } comps->insert( EComps::value_type(comp->getId(), comp) ); return true; } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::removeSource( EComp *comp ) { list::iterator it = sources.begin(); PortComp *cmp = NULL; for( ; it != sources.end(); it++ ) { if( **it == *comp ) { sources.remove( (PortComp *)*it ); cmp = *it; } } if( cmp != NULL ) delete cmp; return true; } /******************************************************************* * Function Name: *******************************************************************/ bool ECircuit::removeGround( EComp *comp ) { list::iterator it = grounds.begin(); Ground *gnd = NULL; for( ; it != grounds.end(); it++ ) { if( **it == *comp ) { grounds.remove( (Ground *)*it ); gnd = *it; } } if( gnd != NULL ) delete gnd; return true; }