Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/506 set data buffer method in storage unit #507

Merged
merged 4 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/Support/bskReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Version |release|
use spherical harmonics and loads them from a file with a single command. Similarly, the methods ``usePolyhedralGravityModel``
and ``usePointMassGravityModel`` have been added.
- Fixed examples and tests to run even when Basilisk is built with ``--vizInterface False``.
- Added a new method ``setDataBuffer()`` to :ref:`simpleStorageUnit` and :ref:`partitionedStorageUnit` to add or remove data from specified partitions.

Version 2.2.0 (June 28, 2023)
-----------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@
DataStorageUnitBase::DataStorageUnitBase(){
this->previousTime = 0; //! - previousTime initialized to 0.
this->nodeDataUseInMsgs.clear(); //! - Clear the vector of input messages.
this->storedDataSum = 0.0; //! - Initialize the dataSum to 0.
this->storedDataSum = 0; //! - Initialize the dataSum to 0.
this->netBaud = 0.0; //! - Initialize the netBaudRate to 0.
//! - Zero out the partitions
for(uint64_t i = 0; i < this->storedData.size(); i++){
this->storedData[i].dataInstanceSum = 0;
}
return;
}

Expand All @@ -49,11 +53,6 @@ void DataStorageUnitBase::Reset(uint64_t CurrentSimNanos)
{
this->previousTime = 0;

//! - Zero out the partitions
for(uint64_t i = 0; i < this->storedData.size(); i++){
this->storedData[i].dataInstanceSum = 0.0;
}

//! - call the custom environment module reset method
customReset(CurrentSimNanos);

Expand Down Expand Up @@ -168,18 +167,18 @@ void DataStorageUnitBase::integrateDataStatus(double currentTime){
index = messageInStoredData(&(*it));

//! - If the storage capacity has not been reached or the baudRate is less than 0 and won't take below 0, then add the data
if ((this->storedDataSum < this->storageCapacity) || (it->baudRate < 0)) {
if ((this->storedDataSum + round(it->baudRate * this->currentTimestep) <= this->storageCapacity) || (it->baudRate < 0)) {
//! - if a dataNode exists in storedData vector, integrate and add to current amount
if (index != -1) {
//! Only perform if this operation will not take the sum below zero
if ((this->storedData[(size_t) index].dataInstanceSum + it->baudRate * (this->currentTimestep)) >= 0) {
this->storedData[(size_t) index].dataInstanceSum += it->baudRate * (this->currentTimestep);
this->storedData[(size_t) index].dataInstanceSum += round(it->baudRate * (this->currentTimestep));
}
//! - if a dataNode does not exist in storedData, add it to storedData, integrate baud rate, and add amount
}
else if (strcmp(it->dataName, "") != 0) {
strncpy(tmpDataInstance.dataInstanceName, it->dataName, sizeof(tmpDataInstance.dataInstanceName));
tmpDataInstance.dataInstanceSum = it->baudRate * (this->currentTimestep);
tmpDataInstance.dataInstanceSum = round(it->baudRate * (this->currentTimestep));
this->storedData.push_back(tmpDataInstance);
}
}
Expand Down Expand Up @@ -214,8 +213,8 @@ int DataStorageUnitBase::messageInStoredData(DataNodeUsageMsgPayload *tmpNodeMsg
/*! Sums all of the data in the storedData vector
@return double
*/
double DataStorageUnitBase::sumAllData(){
double dataSum = 0.0;
long long int DataStorageUnitBase::sumAllData(){
double dataSum = 0;

std::vector<dataInstance>::iterator it;
for(it = storedData.begin(); it != storedData.end(); it++) {
Expand Down Expand Up @@ -248,3 +247,45 @@ bool DataStorageUnitBase::customReadMessages()
{
return true;
}

/*! Adds a specific amount of data to the storedData vector once
@param partitionName //Name of the partition to add data to
@param data //Amount of data to add to the partition
@return void
*/
void DataStorageUnitBase::setDataBuffer(std::string partitionName, long long int data)
{
dataInstance tmpDataInstance;

int index = -1;
for (uint64_t i = 0; i < this->storedData.size(); i++){
if (strcmp(this->storedData[i].dataInstanceName, partitionName.c_str()) == 0){
index = (int) i;
}
}

//! - If the new data won't overflow the storage capacity, then add the data
if (this->storedDataSum + data <= this->storageCapacity) {
//! - if a dataNode exists in storedData vector, integrate and add to current amount
if (index != -1) {
//! Only perform if this operation will not take the sum below zero
if ((this->storedData[(size_t) index].dataInstanceSum + data) >= 0) {
this->storedData[(size_t) index].dataInstanceSum += data;
}

}
//! - if a dataNode does not exist in storedData, add it to storedData, and add amount
else if (strcmp(partitionName.c_str(), "") != 0) {
strncpy(tmpDataInstance.dataInstanceName, partitionName.c_str(), sizeof(tmpDataInstance.dataInstanceName));
//! Only perform this operation if the resulting sum in the partition is not negative. If it is, initialize to zero.
if (data < 0) {
data = 0;
}
tmpDataInstance.dataInstanceSum = data;
this->storedData.push_back(tmpDataInstance);
}
}

//! - Sum all data in storedData vector
this->storedDataSum = this->sumAllData();
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

struct dataInstance {
char dataInstanceName[128]; //!< data instance name
double dataInstanceSum; //!< data instance sum value, bits
long long int dataInstanceSum; //!< data instance sum value, bits
Copy link
Contributor

@patkenneally patkenneally Nov 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize that this has already been merged, but maybe after the break, this can be changed to use the precise width type int64_t or even uint64_t if your semantics demand it. We should prefer precise width types for any integer types larger than int. The bit size of integral types is not guaranteed across platforms/compilers. It benefits us to er on the side of guarantee. You can see (for the large majority) this attempt throughout the code base to use int32_t, int64_t, and the unsigned versions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Howdy @LorenzzoQM , @patkenneally makes some good points here about the use of int64_t, etc. Could you please create a small branch next week to address his feedback? I'll respond to review request quickly so it doesn't slow down your research tasks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I will address the comments as soon as possible. Thank you for the feedback, @patkenneally.

}; //!< Struct for instances of data stored in a buffer. Includes names and amounts.

/*! @brief on-board data handling base class */
Expand All @@ -45,6 +45,7 @@ class DataStorageUnitBase: public SysModel {
void Reset(uint64_t CurrentSimNanos);
void addDataNodeToModel(Message<DataNodeUsageMsgPayload> *tmpNodeMsg); //!< Adds dataNode to the storageUnit
void UpdateState(uint64_t CurrentSimNanos);
void setDataBuffer(std::string partitionName, long long int data); //!< Adds/removes the data from the partitionName partition once

protected:
void writeMessages(uint64_t CurrentClock);
Expand All @@ -54,18 +55,18 @@ class DataStorageUnitBase: public SysModel {
virtual void customWriteMessages(uint64_t CurrentClock); //!< custom Write method, similar to customSelfInit.
virtual bool customReadMessages(); //!< Custom read method, similar to customSelfInit; returns `true' by default.
int messageInStoredData(DataNodeUsageMsgPayload *tmpNodeMsg); //!< Returns index of the dataName if it's already in storedData
double sumAllData(); //!< Sums all of the data in the storedData vector
long long int sumAllData(); //!< Sums all of the data in the storedData vector

public:
std::vector<ReadFunctor<DataNodeUsageMsgPayload>> nodeDataUseInMsgs; //!< Vector of data node input message names
Message<DataStorageStatusMsgPayload> storageUnitDataOutMsg; //!< Vector of message names to be written out by the storage unit
double storageCapacity; //!< Storage capacity of the storage unit
long long int storageCapacity; //!< Storage capacity of the storage unit
BSKLogger bskLogger; //!< logging variable

protected:
DataStorageStatusMsgPayload storageStatusMsg; //!< class variable
std::vector<DataNodeUsageMsgPayload> nodeBaudMsgs; //!< class variable
double storedDataSum; //!< [bits] Stored data in bits.
long long int storedDataSum; //!< [bits] Stored data in bits.
std::vector<dataInstance> storedData; //!< Vector of data. Represents the makeup of the data buffer.
double previousTime; //!< Previous time used for integration
double currentTimestep;//!< [s] Timestep duration in seconds.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ Executive Summary
-----------------
DataStorageUnitBase is a base class that is used generate a standard interface and list of features for modules that store simulated onboard data. This class is used by other modules as a parent class and cannot be instantiated by itself. All Basilisk data storage modules based on this DataStorageUnitBase inherit the following common properties:

1. Writes out a :ref:`DataStorageStatusMsgPayload` containing the sum of the current stored data (in bits), the storage capacity (bits), the current net data rate (in baud), an array of char array containing the names of the stored data (ex. Instrument 1, Instrument 2), and an array of doubles containing the stored data associated with each type (bits).
1. Writes out a :ref:`DataStorageStatusMsgPayload` containing the sum of the current stored data (in bits), the storage capacity (bits), the current net data rate (in baud), an array of char array containing the names of the stored data (ex. Instrument 1, Instrument 2), and an array of integers containing the stored data associated with each type (bits).
2. Allows for multiple :ref:`DataNodeUsageMsgPayload` corresponding to individual :ref:`dataNodeBase` instances to be subscribed to using the ``addDataNodeToModel(msg)`` method.
3. Iterates through attached :ref:`DataNodeUsageMsgPayload` instances, integrates the data for each data node, and adds it to its respective entry using ``integrateDataStatus()`` method, which may be overwritten in child classes.
4. Loops through the vector of storedData to sum the total amount of data contained within the storage unit.
5. Add or remove data from specified partitions using ``setDataBuffer()`` method.

Core functionality is wrapped in the ``integrateDataStatus`` protected virtual void method, which computes the amount of data stored in a storage unit on a module basis. This base class automatically implements a partitioned storage unit (different data buffers for each device). See :ref:`simpleStorageUnit` for an example of how this functionality can be overwritten.

Expand Down
Loading
Loading