/******************************************************* * * DESCRIPTION: QBG capacitor class * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include "qbg_capacitor_fi.h" #include "ini.h" #include "mainsimu.h" #include "defaults.h" #include "functions.h" #include "realprec.h" const RealValue QBGCapacitorFlowIn::DefaultCapacitance = 1; const RealValue QBGCapacitorFlowIn::DefaultInitialLoad = 0; /******************************************************************* * Function Name: QBGCapacitorFlowIn * Description: constructor ********************************************************************/ QBGCapacitorFlowIn::QBGCapacitorFlowIn( const string &name ) : Atomic( name ) , f1p( addInputPort( "f1p" ) ) , e1p( addOutputPort( "e1p" ) ) { try { try { // capacitance string capacitance( MainSimulator::Instance().getParameter( description(), "C" ) ); C = atof( capacitance.data() ); } catch ( MException &exc ) { C = DefaultCapacitance; } if ( C <= 0 ) { throw MException( "Invalid Capacitance value : " + Value2StrReal( C ) ); } try { // initial load string load( MainSimulator::Instance().getParameter( description(), "initialLoad" ) ); initialLoad = atof( load.data() ); } catch ( MException &exc ) { initialLoad = DefaultInitialLoad; } if ( initialLoad < 0 ) { throw MException( "Invalid initial load: " + Value2StrReal( initialLoad ) ); } // Quantum try { string quant( MainSimulator::Instance().getParameter( description(), "quantum" ) ); quantum = atof( quant.data() ); } catch ( MException &e ) { quantum = DEFAULT_QUANTUM; } if( quantum <= 0 ) { throw MException( "Invalid quantum value : " + Value2StrReal( quantum ) ); } // Hysteresis window try { string hystW( MainSimulator::Instance().getParameter( description(), "hystWindow" ) ); hystWindow = atof( hystW.data() ); } catch ( MException &e ) { hystWindow = DEFAULT_HYST_WINDOW; } if( hystWindow < 0 ) { throw MException( "Invalid hysteresis window value : " + Value2StrReal( hystWindow ) ); } createQuantizer(); // Output file try { outFileName = MainSimulator::Instance().getParameter( description(), "outputFile" ); } catch ( MException &e ) { outFileName = DEFAULT_QBG_OUTFILENAME; } } catch ( MException &e ) { e.print( cerr ); MTHROW( e ) ; } } /******************************************************************* * Function Name: ~QBGCapacitorFlowIn * Destructor ********************************************************************/ QBGCapacitorFlowIn::~QBGCapacitorFlowIn() { if( quantizer != NULL ) { delete quantizer; } outFile.close(); } /******************************************************************* * Function Name: createQuantizer ********************************************************************/ Model &QBGCapacitorFlowIn::createQuantizer() { quantizer = new UniformQuantizer(); assert( quantizer ); ((UniformQuantizer *)quantizer)->setQuantum( quantum ); return *this; } /******************************************************************* * Function Name: initFunction ********************************************************************/ Model &QBGCapacitorFlowIn::initFunction() { c = quantizer->quantize( initialLoad ); qValue = c + quantum; time = 0; der = 0; init = true; eps1 = quantum/2; eps2 = ( quantum - hystWindow )/2; // out file outFile.open( outFileName.c_str() ); outFile << "\nTime, Flow, Effort"; holdIn( active, Time::Zero ); return *this ; } /******************************************************************* * Function Name: externalFunction ********************************************************************/ Model &QBGCapacitorFlowIn::externalFunction( const ExternalMessage &msg ) { RealValue currTime = msg.time().asMsecs(); RealValue nextTime; RealValue val = msg.value(); RealValue e; RealValue func; flow = val; e = currTime - time; val = val * TICK_VALUE; // en msecs val = val * 1/C; if( TRUNCATE( fabs( val ), TOLERANCE ) == 0 ) { time = currTime; c = c + der * e; der = 0; passivate(); } else { func = c + der * e; if( val > 0 ) { if ( der < 0 ) { qValue += quantum; } nextTime = fabs( ( qValue + eps1 - func ) / val ); } else { if ( init ) { qValue -= quantum; init = false; } if ( der > 0 ) { qValue -= quantum; } nextTime = fabs( ( func - ( qValue - hystWindow - eps2 ) ) / val ); } RealValue waitTime = nextTime * TICK_VALUE; time = currTime; c = func; der = val; nc = c + der * nextTime; holdIn( active, Time( static_cast( waitTime ) ) ); } return *this ; } /******************************************************************* * Function Name: internalFunction ********************************************************************/ Model &QBGCapacitorFlowIn::internalFunction( const InternalMessage &msg ) { RealValue currTime = msg.time().asMsecs(); RealValue nextTime; RealValue e; RealValue func; e = currTime - time; func = c + der * e; if( TRUNCATE( fabs( der ), TOLERANCE ) == 0 ) { passivate(); } else if( der > 0 && ( fabs( qValue - quantizer->quantize( func ) ) > TOLERANCE ) ) { // El quantum es muy chico, precision no soportada MException e( "Precision not supported by the simulator! Increase the quantum value for component " + description() ); throw e; } else if( ( der < 0 ) && ( ( func > ( qValue - hystWindow ) ) || ( func < ( qValue - quantum ) ) ) ) { // El quantum es muy chico, precision no soportada MException e( "Precision not supported by the simulator! Increase the quantum value for component " + description() ); throw e; } else { if( der > 0 ) { qValue += quantum; nextTime = fabs( ( qValue + eps1 - func ) / der ); } else { qValue -= quantum; nextTime = fabs( ( func - ( qValue - hystWindow - eps2 ) ) / der ); } RealValue waitTime = nextTime * TICK_VALUE; time = currTime; c = func; nc = c + der * nextTime; holdIn( active, Time( static_cast( waitTime ) ) ); } return *this ; } /******************************************************************* * Function Name: outputFunction ********************************************************************/ Model &QBGCapacitorFlowIn::outputFunction( const InternalMessage &msg ) { sendOutput( msg.time(), e1p, nc ) ; outFile << "\n" << msg.time().asMsecs() << "," << flow << "," << quantizer->quantize( nc ); return *this ; }