Skip to content

Commit

Permalink
Add support for actuating schedules
Browse files Browse the repository at this point in the history
  • Loading branch information
kbenne committed Mar 17, 2020
1 parent e443d63 commit 26fd4ac
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 26 deletions.
7 changes: 7 additions & 0 deletions cli/iddtypes.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#include <array>

constexpr std::array<const char *,4> supportedScheduleTypes = {
"Schedule:Year",
"Schedule:Compact",
"Schedule:Constant",
"Schedule:File"
};

constexpr std::array<const char *,312> supportedIDDTypes = {
"Version",
"SimulationControl",
Expand Down
34 changes: 20 additions & 14 deletions epfmi/EPComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,23 @@ void EPComponent::exchange()
resetActuator(h);
};

auto actuateVar = [&](const Variable & var) {
if( var.valueset ) {
compSetActuatorValue(
var.actuatorcomponentkey,
var.actuatorcomponenttype,
var.actuatorcontroltype,
var.value
);
} else {
compResetActuator(
var.actuatorcomponentkey,
var.actuatorcomponenttype,
var.actuatorcontroltype
);
}
};

// Update inputs first, then outputs so that we can do some updates within EnergyPlus
for( auto & varmap : variables ) {
auto & var = varmap.second;
Expand All @@ -207,21 +224,10 @@ void EPComponent::exchange()
}
break;
case VariableType::EMS_ACTUATOR:
if( var.valueset ) {
compSetActuatorValue(
var.actuatorcomponentkey,
var.actuatorcomponenttype,
var.actuatorcontroltype,
var.value
);
} else {
compResetActuator(
var.actuatorcomponentkey,
var.actuatorcomponenttype,
var.actuatorcontroltype
);
}
actuateVar(var);
break;
case VariableType::SCHEDULE:
actuateVar(var);
default:
break;
}
Expand Down
65 changes: 56 additions & 9 deletions epfmi/Variables.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Variables.hpp"
#include "../cli/iddtypes.hpp"
#include "EnergyPlus/InputProcessing/IdfParser.hh"
#include "EnergyPlus/InputProcessing/EmbeddedEpJSONSchema.hh"
#include "EnergyPlus/DataStringGlobals.hh"
Expand All @@ -13,7 +14,8 @@ using json = nlohmann::json;
//namespace EnergyPlus {
//namespace FMI {

struct FMUInfo {
class FMUInfo {
public:
FMUInfo(const std::string & idfPath)
{
std::ifstream input_stream(idfPath, std::ifstream::in);
Expand All @@ -29,24 +31,49 @@ struct FMUInfo {
::nlohmann::json schema = json::from_cbor(embeddedEpJSONSchema.first, embeddedEpJSONSchema.second);
jsonidf = parser.decode(input_file, schema);

initZoneNames();
initSchedules();
}

std::vector<std::string> zoneNames() const {
std::vector<std::string> result;
// Given the name of a schedule, return the idd type
// If multiple schedules of the same name, but different type
// are located in the idf, then the return value is ambiguous, and non determinant
std::string scheduleType(const std::string & name) const {
const auto & scheduleit = schedules.find(name);
if( scheduleit != std::end(schedules)) {
return scheduleit->second;
}

return "";
}

std::vector<std::string> zonenames;

private:

void initSchedules() {
for(const auto & type : supportedScheduleTypes) {
for(const auto & schedule : jsonidf[type].items()) {
schedules[schedule.key()] = type;
}
}
}

void initZoneNames() {
std::string type = "Zone";

if ( jsonidf.find(type) != jsonidf.end() ) {
const auto zones = jsonidf[type];
for( const auto & zone : zones.items() ) {
result.push_back(zone.key());
zonenames.push_back(zone.key());
}
}

std::sort(result.begin(), result.end());

return result;
std::sort(zonenames.begin(), zonenames.end());
}

// Key is a schedule name, value is the corresponding schedule type
std::map<std::string, std::string> schedules;
nlohmann::json jsonidf;
};

Expand All @@ -55,7 +82,7 @@ std::map<unsigned int, Variable> parseVariables(const std::string & idf,
{
std::map<unsigned int, Variable> result;

FMUInfo fmuInfo(idf);
FMUInfo fmuinfo(idf);

unsigned int i = 0;

Expand All @@ -69,6 +96,26 @@ std::map<unsigned int, Variable> parseVariables(const std::string & idf,
j = json::parse(jsonInput, nullptr, false);
}

const auto schedules = j.value("model",json()).value("schedules", std::vector<json>(0));
for (const auto & schedule : schedules) {
Variable var;
var.type = VariableType::SCHEDULE;
var.name = schedule.at("fmiName").get<std::string>();
const auto & idfname = schedule.at("name").get<std::string>();
var.actuatorcomponentkey = idfname;
var.actuatorcomponenttype = fmuinfo.scheduleType(idfname);
var.actuatorcontroltype = "Schedule Value";

var.scalar_attributes.emplace_back(std::make_pair("name",var.name));
var.scalar_attributes.emplace_back(std::make_pair("valueReference", std::to_string(i)));
var.scalar_attributes.emplace_back(std::make_pair("description","Schedule"));
var.scalar_attributes.emplace_back(std::make_pair("causality","input"));
var.scalar_attributes.emplace_back(std::make_pair("variability","continuous"));

result.emplace(i,std::move(var));
++i;
}

const auto outputVariables = j.value("model",json()).value("outputVariables", std::vector<json>(0));
for (const auto & outputVariable : outputVariables) {
auto epname = outputVariable.at("name").get<std::string>();
Expand Down Expand Up @@ -111,7 +158,7 @@ std::map<unsigned int, Variable> parseVariables(const std::string & idf,
++i;
}

const auto zones = fmuInfo.zoneNames();
const auto zones = fmuinfo.zonenames;
for (const auto & zone : zones) {
{
Variable var;
Expand Down
3 changes: 2 additions & 1 deletion epfmi/Variables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ enum class VariableType {
X,
MINLETS_FLOW,
SENSOR,
EMS_ACTUATOR
EMS_ACTUATOR,
SCHEDULE
};

using VariableAttribute = std::pair<std::string, std::string>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"name": "People Occupant Count",
"key": "Core_ZN People",
"fmiName": "Core_Zone_People_Output"
},
{
"name": "Lights Electric Power",
"key": "Core_ZN_Lights",
"fmiName": "Core_Zone_Lights_Output"
}
],
"emsActuators": [
Expand All @@ -39,6 +44,13 @@
"unit" : "1",
"fmiName" : "Core_Zone_People"
}
]
}
],
"schedules": [
{
"name" : "BLDG_LIGHT_SCH",
"unit" : "1",
"fmiName" : "Lights_Schedule"
}
]
}
}
6 changes: 6 additions & 0 deletions examples/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@
model.time = t
model.set('Core_ZN_T', temp);
people = 0
lights = 0
if t % 120 == 0:
people = 5
lights = 1
else:
people = 1
lights = 0

model.set('Core_Zone_People', people)
model.set('Lights_Schedule', lights)

print("t = " + str(t))
print("temp = " + str(temp))
Expand All @@ -70,6 +74,8 @@
print("Core_ZN_QConSen_flow: ", model.get('Core_ZN_QConSen_flow')[0])
print("people = " + str(people))
print("Core_Zone_People_Output: ", model.get('Core_Zone_People_Output')[0])
print("lights = " + str(lights))
print("Core_Zone_Lights_Output: ", model.get('Core_Zone_Lights_Output')[0])

dt = t - last_time
tempDot = model.get('Core_ZN_QConSen_flow')[0] / ( volume * densityAir * heatCapacity );
Expand Down

0 comments on commit 26fd4ac

Please sign in to comment.