/******************************************************* * * DESCRIPTION: Bond Graph components classes * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #ifndef BGCOMPS_H #define BGCOMPS_H #include #include "strutil.h" #include "signal.h" #include "excepts.h" #include "defaults_mapping.h" #define INVALID_CAUSALITY_ERROR_MSG "Invalid causalization for component " #define INVERSE_CAUSALITY( x ) ( ( x == EffortIn ) ? EffortOut : EffortIn ) //------------------------------- // Tipos y estructuras //------------------------------- typedef string Id; typedef enum { EffortIn, EffortOut, Any } Causality; typedef enum { FixedCausality, PreferredCausality, RestrictedCausality, VarCausality } CausalityType; typedef enum { PowerIn, PowerOut, PowerThrough, NullP } PowerDir; //--- forward declarations --- class BondGraph; //****************************************************** // // Class BGEdgeData // // Description: clase para los ejes de un Bond Graph // //****************************************************** class BGEdgeData { public: BGEdgeData() { id = int2Str( count ); powerDirDest = NULL_ID; causalityDest = NULL_ID; count++; } BGEdgeData( const Id &eid ) { id = eid; powerDirDest = NULL_ID; causalityDest = NULL_ID; } BGEdgeData( const Id &powerDest, const Id &causalDest ) { id = int2Str( count ); powerDirDest = powerDest; causalityDest = causalDest; count++; } BGEdgeData( const Id &eid, const Id &powerDest, const Id &causalDest ) { id = eid; powerDirDest = powerDest; causalityDest = causalDest; } virtual ~BGEdgeData() {}; bool hasPowerDir() { return ( powerDirDest != NULL_ID ); } bool isCausalized() { return ( causalityDest != NULL_ID ); } Id getId() const { return id; } Id getPowerDirDest() const { return powerDirDest; } Id getCausalityDirDest() const { return causalityDest; } void setId( const Id &eid ) { id = eid; } void setPowerDirDest( const Id &powerDest ) { powerDirDest = powerDest; } void setCausalityDest( const Id &causalDest ) { causalityDest = causalDest; } bool isPowerDest( const Id &did ) const { return ( powerDirDest == did ); } bool isCausalityDest( const Id &did ) const { return ( causalityDest == did ); } string asString() const; BGEdgeData & operator == ( const BGEdgeData &data ); ostream& operator << ( ostream &out ); private: Id id; Id powerDirDest; Id causalityDest; static int count; }; //------------------------------- // inline functions //------------------------------- inline string BGEdgeData::asString() const { return ( id + "," + ( powerDirDest == NULL_ID ? "Null" : powerDirDest ) + "," + ( causalityDest == NULL_ID ? "Null" : causalityDest ) ); } inline ostream& BGEdgeData::operator << ( ostream &out ) { out << asString(); return out; } inline ostream &operator <<( ostream &os, const BGEdgeData &edge ) { os << edge.asString(); return os; } //****************************************************** // // Class BGComp // // Description: componente Bond Graph genérico // //****************************************************** class BGComp { public: virtual ~BGComp() {}; virtual string className() const { return "BGComp"; } Id getId() const { return this->id; } virtual CausalityType getCausalityType() const { return causalityType; } virtual Causality getAllowedCausality() const { return allowedCausality; } virtual Causality getPreferredCausality() const { return allowedCausality; } virtual PowerDir getPowerDir() const { return powerDir; } virtual void setPowerDirToEdge( BGEdgeData &, const BGComp & ) const {}; virtual int getLastBondAssigned() const { return lastBondAssigned; } virtual void incLastBondAssigned() { lastBondAssigned++; } virtual bool isJunction() const { return false; } virtual BGComp &operator = ( const BGComp & ); virtual bool operator == ( const BGComp &c ) { return c.id == id; } virtual string causalizedComponentName() const { return className(); } virtual string getVarsAsString() const { return ""; } bool marked() const { return mark; } void setMark( const bool mark = true ) { this->mark = mark; } virtual bool quantifiable() const { return false; } virtual int generateBondId( const BGEdgeData & edge ) { int aret = lastBondAssigned; lastBondAssigned++; return aret; } protected: BGComp( const Id & ); BGComp( const Id &, const CausalityType & ); BGComp( const Id &, const CausalityType &, const Causality &, const PowerDir & ); virtual void updateAllowedCausality( const Causality &caus ) { allowedCausality = caus; } friend class BondGraph; Id id; CausalityType causalityType; Causality allowedCausality; PowerDir powerDir; int lastBondAssigned; bool mark; }; //****************************************************** // // Class BGGround // // Description: componente para representar ground // (no pertenece a los componentes básicos // de Bond Graph, sólo es usado temporalmente) // //****************************************************** class BGGround : public BGComp { public: BGGround( const Id &id ) :BGComp( id, FixedCausality, EffortOut, PowerIn ) {}; string className() const { return "BGGround"; } }; //****************************************************** // // Class BGResistance // // Description: componente resistencia de Bond Graph // //****************************************************** class BGResistance : public BGComp { public: BGResistance( const Id &id, const RealValue r ); ~BGResistance() {}; string className() const { return "BGResistance"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( id ); } BGResistance &operator = ( const BGResistance &r ); virtual string causalizedComponentName() const { return ( ( allowedCausality == EffortIn ? "BGResistanceEffortIn" : "BGResistanceFlowIn" ) ); } virtual string getVarsAsString() const; private: RealValue R; }; //------------------------------- // inline functions //------------------------------- inline BGResistance::BGResistance( const Id &id, const RealValue r ) :BGComp( id, VarCausality, Any, PowerIn ) { R = r; } inline BGResistance &BGResistance::operator = ( const BGResistance &r ) { BGComp::operator = ( r ); R = r.R; return *this; } inline string BGResistance::getVarsAsString() const { return ( BGComp::getVarsAsString() + "R : " + Value2StrReal( R ) ); } //****************************************************** // // Class BGCapacitor // // Description: componente capacitor (storage) de Bond // Graph (sólo se encuentra implementado // el storage con causalidad integral) // //****************************************************** class BGCapacitor : public BGComp { public: BGCapacitor( const Id &id, const RealValue c, const RealValue initLoad = 0 ); ~BGCapacitor() {}; string className() const { return "BGCapacitor"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( id ); } BGCapacitor &operator = ( const BGCapacitor &c ); virtual string causalizedComponentName() const { return "BGCapacitorFlowIn"; } virtual string getVarsAsString() const; virtual bool quantifiable() const { return true; } virtual Causality getPreferredCausality() const { return EffortOut; } protected: private: RealValue C; RealValue initialLoad; }; //------------------------------- // inline functions //------------------------------- inline BGCapacitor::BGCapacitor( const Id &id, const RealValue c, const RealValue initLoad ) :BGComp( id, PreferredCausality, EffortOut, PowerIn ) { C = c; initialLoad = initLoad; } inline BGCapacitor &BGCapacitor::operator = ( const BGCapacitor &c ) { BGComp::operator = ( c ); C = c.C; initialLoad = c.initialLoad; return *this; } //****************************************************** // // Class BGInductor // // Description: componente inductor (storage) de Bond // Graph (sólo se encuentra implementado // el storage con causalidad integral) // //****************************************************** class BGInductor : public BGComp { public: BGInductor( const Id &id, const RealValue i, const RealValue initLoad = 0 ); ~BGInductor() {}; string className() const { return "BGInductor"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( id ); } BGInductor &operator = ( const BGInductor &i ); virtual string causalizedComponentName() const { return "BGInductorEffortIn"; } virtual string getVarsAsString() const; virtual bool quantifiable() const { return true; } virtual Causality getPreferredCausality() const { return EffortIn; } protected: private: RealValue I; RealValue initialLoad; }; //------------------------------- // inline functions //------------------------------- inline BGInductor::BGInductor( const Id &id, const RealValue i, const RealValue initLoad ) :BGComp( id, PreferredCausality, EffortIn, PowerIn ) { I = i; initialLoad = initLoad; } inline BGInductor &BGInductor::operator = ( const BGInductor &i ) { BGComp::operator = ( i ); I = i.I; initialLoad = i.initialLoad; return *this; } //****************************************************** // // Class BGTransformer // // Description: componente transformador de Bond Graph // //****************************************************** class BGTransformer : public BGComp { public: BGTransformer( const Id &id, const RealValue t ) :BGComp( id, RestrictedCausality, Any, NullP ) { T = t; pCount = 1; } ~BGTransformer() {}; string className() const { return "BGTransformer"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( this->getId() ); } Causality getAllowedCausality() const; BGTransformer &operator = ( const BGTransformer &t ) { BGComp::operator = (t ); T = t.T; return *this; } virtual string getVarsAsString() const { return ( BGComp::getVarsAsString() + "T : " + Value2StrReal( T ) ); } int generateBondId( const BGEdgeData & edge ); protected: void updateAllowedCausality( const Causality &caus ); private: RealValue T; int pCount; }; //------------------------------- // inline functions //------------------------------- inline Causality BGTransformer::getAllowedCausality() const { if ( allowedCausality == Any ) return allowedCausality; return INVERSE_CAUSALITY( allowedCausality ); } inline void BGTransformer::updateAllowedCausality( const Causality &caus ) { if( allowedCausality == Any ) allowedCausality = caus; else if( caus == Any ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); else if( allowedCausality != INVERSE_CAUSALITY( caus ) ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); allowedCausality = caus; } inline int BGTransformer::generateBondId( const BGEdgeData & edge ) { if( edge.isCausalityDest( this->getId() ) ) { return 1; } return 2; } //****************************************************** // // Class BGGyrator // // Description: componente girador de Bond Graph // //****************************************************** class BGGyrator : public BGComp { public: BGGyrator( const Id &id, const RealValue g ) :BGComp( id, RestrictedCausality, Any, NullP ) { G = g; } ~BGGyrator() {}; string className() const { return "BGGyrator"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( this->getId() ); } BGGyrator &operator = ( const BGGyrator &g ) { BGComp::operator = ( g ); G = g.G; return *this; } virtual string causalizedComponentName() const { return ( allowedCausality == EffortIn ? "BGGyratorEffortIn" : "BGGyratorFlowIn" ); } virtual string getVarsAsString() const { return ( BGComp::getVarsAsString() + "G : " + Value2StrReal( G ) ); } protected: void updateAllowedCausality( const Causality &caus ); private: RealValue G; }; //------------------------------- // inline functions //------------------------------- inline void BGGyrator::updateAllowedCausality( const Causality &caus ) { if( allowedCausality == Any ) allowedCausality = caus; if( allowedCausality != caus ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); } //****************************************************** // // Class BGSourceEffort // // Description: fuente de effort de Bond Graph // //****************************************************** class BGSourceEffort : public BGComp { public: BGSourceEffort( const Id &id, Signal *ssignal ) :BGComp( id, FixedCausality, EffortOut, PowerOut ) { assert( ssignal ); signal = ssignal; } ~BGSourceEffort() {}; string className() const { return "BGSourceEffort"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( comp.getId() ); } BGSourceEffort &operator = ( const BGSourceEffort &s ) { BGComp::operator = ( s ); signal = s.signal; return *this; } virtual string getVarsAsString() const; virtual string causalizedComponentName() const { return ( className() + "_" + signal->name() ); } virtual bool quantifiable() const { return true; } protected: void updateAllowedCausality( const Causality &caus ); private: Signal *signal; }; //------------------------------- // inline functions //------------------------------- inline void BGSourceEffort::updateAllowedCausality( const Causality &caus ) { if ( caus != EffortOut ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); } //****************************************************** // // Class BGSourceFlow // // Description: fuente de flujo de Bond Graph // //****************************************************** class BGSourceFlow : public BGComp { public: BGSourceFlow( const Id &id, Signal *s ) :BGComp( id, FixedCausality, EffortIn, PowerOut ) { assert( s ); signal = s; } ~BGSourceFlow() {}; string className() const { return "BGSourceFlow"; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const { edge.setPowerDirDest( comp.getId() ); } BGSourceFlow &operator = ( const BGSourceFlow &s ) { BGComp::operator = ( s ); signal = s.signal; return *this; } virtual string getVarsAsString() const; virtual string causalizedComponentName() const { return ( className() + "_" + signal->name() ); } virtual bool quantifiable() const { return true; } protected: void updateAllowedCausality( const Causality &caus ); private: Signal *signal; }; //------------------------------- // inline functions //------------------------------- inline void BGSourceFlow::updateAllowedCausality( const Causality &caus ) { if ( caus != EffortIn ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); } //****************************************************** // // Class BGSerialJunction // // Description: junction serial (1-junction) de Bond Graph // //****************************************************** class BGSerialJunction : public BGComp { public: BGSerialJunction() :BGComp( "$SJ" + int2Str( count ), RestrictedCausality, Any, NullP ) { effortOutAssigned = false; lastBondAssigned = 2; count++; } ~BGSerialJunction() {}; string className() const { return "BGSerialJunction"; } bool isJunction() const { return true; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const; Causality getAllowedCausality() const; BGSerialJunction &operator = ( const BGSerialJunction &j ) { BGComp::operator = ( j ); effortOutAssigned = j.effortOutAssigned; return *this; } int generateBondId( const BGEdgeData & edge ); protected: void updateAllowedCausality( const Causality &caus ); private: static int count; bool effortOutAssigned; }; //------------------------------- // inline functions //------------------------------- inline Causality BGSerialJunction::getAllowedCausality() const { if ( effortOutAssigned ) return EffortIn; return Any; } inline void BGSerialJunction::updateAllowedCausality( const Causality &caus ) { if( effortOutAssigned && caus != EffortIn ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); if( caus == EffortOut ) effortOutAssigned = true; allowedCausality = caus; } //****************************************************** // // Class BGParallelJunction // // Description: junction paralelo (0-junction) de Bond Graph // //****************************************************** class BGParallelJunction : public BGComp { public: BGParallelJunction() :BGComp( "$PJ" + int2Str( count ), RestrictedCausality, Any, NullP ) { effortInAssigned = false; lastBondAssigned = 2; count++; } ~BGParallelJunction() {}; string className() const { return "BGParallelJunction"; } bool isJunction() const { return true; } void setPowerDirToEdge( BGEdgeData &edge, const BGComp &comp ) const; Causality getAllowedCausality() const; BGParallelJunction &operator = ( const BGParallelJunction &j ) { BGComp::operator = ( j ); effortInAssigned = j.effortInAssigned; return *this; } int generateBondId( const BGEdgeData & edge ); protected: void updateAllowedCausality( const Causality &caus ); private: static int count; bool effortInAssigned; }; //------------------------------- // inline functions //------------------------------- inline Causality BGParallelJunction::getAllowedCausality() const { if ( effortInAssigned ) return EffortOut; return Any; } inline void BGParallelJunction::updateAllowedCausality( const Causality &caus ) { if( effortInAssigned && caus != EffortOut ) throw BGCompException( INVALID_CAUSALITY_ERROR_MSG ); if( caus == EffortIn ) effortInAssigned = true; allowedCausality = caus; } #endif