Conversation
pelesh
left a comment
There was a problem hiding this comment.
In this first cut I suggest we implement signal bus as a standalone class inheriting directly from Model::Evaluator.
|
Okay, I have performed the following:
After this merge, I will make the following Issues:
Seeking further review @pelesh and @abirchfield . Hoping we unlock doors with this PR! |
superwhiskers
left a comment
There was a problem hiding this comment.
some minor suggestions. i don't think i have any major comments.
| // if(is_initialized_) | ||
| //{ | ||
| // std::cout << "ERROR!"; | ||
| // } | ||
| // else{ | ||
| // y_[0] = value; | ||
| // is_initialized_ = true; | ||
| // } |
There was a problem hiding this comment.
why is this commented out? it appears to implement the intended behavior but instead we always set y_[0] to the value provided.
| /** | ||
| * @brief A one-time initialization function | ||
| * that can be called by any. | ||
| * | ||
| * @return state value of signal | ||
| */ | ||
| void initial_value(ScalarT value) override |
There was a problem hiding this comment.
this method should be called initialValue to follow the naming conventions we have.
| /** | ||
| * @brief A helper function to easily init | ||
| * a signal value wiithout needing to check if initialized | ||
| * | ||
| * @param signal The signal bus object pointer | ||
| * @param value The value to send to the equality constraint | ||
| */ | ||
| void safeInit(bus_type* signal, ScalarT value) | ||
| { | ||
| if (signal) | ||
| { | ||
| signal->initial_value(value); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @brief A helper function to easily init | ||
| * a signal value wiithout needing to check if initialized | ||
| * | ||
| * @param signal The signal bus object pointer | ||
| * @param value The value to send to the equality constraint | ||
| */ | ||
| void safeWrite(bus_type* signal, ScalarT value) | ||
| { | ||
| if (signal) | ||
| { | ||
| signal->write(value); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @brief A helper function to easily read | ||
| * the state of the signal without checking nullptr | ||
| * | ||
| * | ||
| * @param signal The signal bus object pointer | ||
| * @param default_val The value to return if no signal | ||
| */ | ||
| ScalarT safeRead(bus_type* signal, ScalarT default_val) | ||
| { | ||
| if (signal) | ||
| { | ||
| return signal->read(); | ||
| } | ||
| else | ||
| { | ||
| return default_val; | ||
| } | ||
| } |
There was a problem hiding this comment.
i'm not sure these would belong on the Component class to be totally honest. they seem to exclusively be helper functions with no need to access any private data present on a Component; i think they would make more sense as standalone functions in a Utility.hpp file or something present within src/Model/PhasorDynamics.
| { | ||
| bus, ///< Unique ID of the connecting bus | ||
| pmech_signal, ///< Unique ID of the governor Pmech signal. | ||
| speed_signal, ///< Unique ID of the speed signal of the machine. |
There was a problem hiding this comment.
we should also modify src/Model/PhasorDynamics/INPUT_FORMAT.md if we're adding new ports
| IdxT pmech_index = 0; | ||
| IdxT speed_index = 0; | ||
|
|
||
| bool has_bus = gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::bus); | ||
| bool has_pmech_signal = gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::pmech_signal); | ||
| bool has_speed_signal = gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::speed_signal); | ||
|
|
||
| if (has_bus && has_pmech_signal && has_speed_signal) | ||
| { | ||
|
|
||
| bus_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::bus); | ||
| pmech_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::pmech_signal); | ||
| speed_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::speed_signal); | ||
|
|
||
| auto* gen = new Genrou<ScalarT, IdxT>( | ||
| getBus(bus_index), | ||
| getBus(pmech_index), | ||
| getBus(speed_index), | ||
| gendata); | ||
| addComponent(gen); | ||
| } | ||
| else{ | ||
| bus_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::bus); | ||
|
|
||
| auto* gen = new Genrou<ScalarT, IdxT>( | ||
| getBus(bus_index), | ||
| nullptr, | ||
| nullptr, | ||
| gendata); | ||
| addComponent(gen); | ||
| } |
There was a problem hiding this comment.
| IdxT pmech_index = 0; | |
| IdxT speed_index = 0; | |
| bool has_bus = gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::bus); | |
| bool has_pmech_signal = gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::pmech_signal); | |
| bool has_speed_signal = gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::speed_signal); | |
| if (has_bus && has_pmech_signal && has_speed_signal) | |
| { | |
| bus_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::bus); | |
| pmech_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::pmech_signal); | |
| speed_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::speed_signal); | |
| auto* gen = new Genrou<ScalarT, IdxT>( | |
| getBus(bus_index), | |
| getBus(pmech_index), | |
| getBus(speed_index), | |
| gendata); | |
| addComponent(gen); | |
| } | |
| else{ | |
| bus_index = gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::bus); | |
| auto* gen = new Genrou<ScalarT, IdxT>( | |
| getBus(bus_index), | |
| nullptr, | |
| nullptr, | |
| gendata); | |
| addComponent(gen); | |
| } | |
| bus_type* bus = nullptr; | |
| bus_type* pmech = nullptr; | |
| bus_type* speed = nullptr; | |
| if (gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::bus)) | |
| { | |
| bus = getBus(gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::bus)); | |
| } | |
| if (gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::pmech_signal)) | |
| { | |
| pmech = getBus(gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::pmech_signal)); | |
| } | |
| if (gendata.ports.contains(GenrouData<ScalarT, IdxT>::Ports::speed_signal)) | |
| { | |
| speed = getBus(gendata.ports.at(GenrouData<ScalarT, IdxT>::Ports::speed_signal)); | |
| } | |
| auto* gen = new Genrou<ScalarT, IdxT>(bus, pmech, speed, gendata); | |
| addComponent(gen); |
you can make this much cleaner
| /* Need to add signals to gendata class */ | ||
| auto* gov = new Governor::Tgov1<ScalarT, IdxT>( | ||
| getBus(govdata.signal_pmech), | ||
| getBus(govdata.signal_speed), | ||
| govdata); |
There was a problem hiding this comment.
is it the case with Tgov1 that these signals are non-optional? (that sounds correct to me but i want to make sure as it is not documented in the input format)
|
Closing this for now, but we can revisit this implementation approach later. |
Description
A preliminary BusSignal implementation that is a stepping point to a fully developed Bus Hierarchy. Supported signals can be specified by the Data structure input.
Closes Issue #154
An exciter model implementation and validated example (see branch IEEET1) are ready for PR once this is merged
Proposed changes
Checklist
-Wall -Wpedantic -Wconversion -Wextra.Further comments
The cmake of many filles had to be changed to include the governor program since I added it to the SystemModel. Is there a better way to have files that use SystemModel to not require all the same programs?
Future PR will need to create seperate bases: BusElectricalBase and BusSignalBase. This is a temporary solutions before these new bases are formed, because that task is large to undertake.
Forgive the large quantity of commits. I have a VM in addition to local WSL, so I am making frequent commits to the origin.