Skip to content

Commit

Permalink
Merge pull request #4454 from NREL/4404_excludeLCC
Browse files Browse the repository at this point in the history
Fix #4404 #4453 - Fix issues with ForwardTranslator options
  • Loading branch information
tijcolem authored Oct 5, 2021
2 parents 81c7067 + 1dff48b commit 65607ae
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 26 deletions.
53 changes: 27 additions & 26 deletions src/energyplus/ForwardTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@

#include "../utilities/idd/IddEnums.hpp"

#include <thread>

#include <algorithm>
#include <sstream>
#include <thread>

using namespace openstudio::model;

Expand Down Expand Up @@ -464,22 +464,25 @@ namespace energyplus {
translateAndMapModelObject(*runPeriod);

// ensure that output table summary reports exists
boost::optional<model::OutputTableSummaryReports> optOutputTableSummaryReports =
model.getOptionalUniqueModelObject<model::OutputTableSummaryReports>();
if (!optOutputTableSummaryReports) {
OutputTableSummaryReports outputTableSummaryReports = model.getUniqueModelObject<model::OutputTableSummaryReports>();
outputTableSummaryReports.addSummaryReport("AllSummary");
translateAndMapModelObject(outputTableSummaryReports);
// If the user manually added an OutputTableSummaryReports, but he also opted-in to exclude it on the FT, which decision do we keep?
// Given that it's a much harder to set the option on the FT, I'll respect that one
if (!m_excludeHTMLOutputReport) {
auto optOutputTableSummaryReports = model.getOptionalUniqueModelObject<model::OutputTableSummaryReports>();
// Add default one if none explicitly specified
if (!optOutputTableSummaryReports) {
auto outputTableSummaryReports = model.getUniqueModelObject<model::OutputTableSummaryReports>();
outputTableSummaryReports.addSummaryReport("AllSummary");
translateAndMapModelObject(outputTableSummaryReports);
}
}

// add a global geometry rules object
IdfObject globalGeometryRules(openstudio::IddObjectType::GlobalGeometryRules);
auto& globalGeometryRules = m_idfObjects.emplace_back(openstudio::IddObjectType::GlobalGeometryRules);
globalGeometryRules.setString(openstudio::GlobalGeometryRulesFields::StartingVertexPosition, "UpperLeftCorner");
globalGeometryRules.setString(openstudio::GlobalGeometryRulesFields::VertexEntryDirection, "Counterclockwise");
globalGeometryRules.setString(openstudio::GlobalGeometryRulesFields::CoordinateSystem, "Relative");
globalGeometryRules.setString(openstudio::GlobalGeometryRulesFields::DaylightingReferencePointCoordinateSystem, "Relative");
globalGeometryRules.setString(openstudio::GlobalGeometryRulesFields::RectangularSurfaceCoordinateSystem, "Relative");
m_idfObjects.push_back(globalGeometryRules);

// create meters for utility bill objects
std::vector<UtilityBill> utilityBills = model.getConcreteModelObjects<UtilityBill>();
Expand Down Expand Up @@ -4198,24 +4201,22 @@ namespace energyplus {
}

// ensure at least one life cycle cost exists to prevent crash in E+ 8
unsigned numCosts = 0;
for (const IdfObject& object : m_idfObjects) {
if (object.iddObject().type() == openstudio::IddObjectType::LifeCycleCost_NonrecurringCost) {
numCosts += 1;
} else if (object.iddObject().type() == openstudio::IddObjectType::LifeCycleCost_RecurringCosts) {
numCosts += 1;
if (!m_excludeLCCObjects) {
bool hasAtLeastOneCost = std::any_of(m_idfObjects.cbegin(), m_idfObjects.cend(), [](const auto& obj) {
auto iddObjType = obj.iddObject().type();
return (iddObjType == openstudio::IddObjectType::LifeCycleCost_NonrecurringCost)
|| (iddObjType == openstudio::IddObjectType::LifeCycleCost_RecurringCosts);
});

if (!hasAtLeastOneCost) {
// add default cost
auto& idfObject = m_idfObjects.emplace_back(openstudio::IddObjectType::LifeCycleCost_NonrecurringCost);
idfObject.setString(LifeCycleCost_NonrecurringCostFields::Name, "Default Cost");
idfObject.setString(LifeCycleCost_NonrecurringCostFields::Category, "Construction");
idfObject.setDouble(LifeCycleCost_NonrecurringCostFields::Cost, 0.0);
idfObject.setString(LifeCycleCost_NonrecurringCostFields::StartofCosts, "ServicePeriod");
}
}
if (numCosts == 0) {
// add default cost
IdfObject idfObject(openstudio::IddObjectType::LifeCycleCost_NonrecurringCost);
m_idfObjects.push_back(idfObject);

idfObject.setString(LifeCycleCost_NonrecurringCostFields::Name, "Default Cost");
idfObject.setString(LifeCycleCost_NonrecurringCostFields::Category, "Construction");
idfObject.setDouble(LifeCycleCost_NonrecurringCostFields::Cost, 0.0);
idfObject.setString(LifeCycleCost_NonrecurringCostFields::StartofCosts, "ServicePeriod");
}
}

IdfObject ForwardTranslator::createAndRegisterIdfObject(const IddObjectType& idfObjectType, const model::ModelObject& modelObject) {
Expand Down
121 changes: 121 additions & 0 deletions src/energyplus/Test/ForwardTranslator_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,3 +758,124 @@ TEST_F(EnergyPlusFixture, BadVariableName) {
EXPECT_TRUE(s == "Good Name" || s == "Bad, !Name") << s;
}
}

TEST_F(EnergyPlusFixture, ForwardTranslation_Options) {

Model m;
ForwardTranslator ft;

// Defaults
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::LifeCycleCost_Parameters));
EXPECT_EQ(5u, w.numObjectsOfType(IddObjectType::LifeCycleCost_UsePriceEscalation));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::LifeCycleCost_NonrecurringCost));

EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_VariableDictionary));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_SQLite));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_Table_SummaryReports));

auto objs = w.getObjectsByType(IddObjectType::OutputControl_Table_Style);
ASSERT_EQ(1, objs.size());
auto obj = objs[0];
EXPECT_EQ("HTML", obj.getString(0).get());
EXPECT_EQ("None", obj.getString(1, true).get()); // Return default
EXPECT_FALSE(obj.getString(1, false, true)); // not initialized
}

ft.setExcludeLCCObjects(true);
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_Parameters));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_UsePriceEscalation));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_NonrecurringCost));

EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_VariableDictionary));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_SQLite));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_Table_SummaryReports));

auto objs = w.getObjectsByType(IddObjectType::OutputControl_Table_Style);
ASSERT_EQ(1, objs.size());
auto obj = objs[0];
EXPECT_EQ("HTML", obj.getString(0).get());
EXPECT_EQ("None", obj.getString(1, true).get()); // Return default
EXPECT_FALSE(obj.getString(1, false, true)); // not initialized
}

ft.setExcludeVariableDictionary(true);
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_Parameters));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_UsePriceEscalation));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_NonrecurringCost));

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_VariableDictionary));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_SQLite));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_Table_SummaryReports));

auto objs = w.getObjectsByType(IddObjectType::OutputControl_Table_Style);
ASSERT_EQ(1, objs.size());
auto obj = objs[0];
EXPECT_EQ("HTML", obj.getString(0).get());
EXPECT_EQ("None", obj.getString(1, true).get()); // Return default
EXPECT_FALSE(obj.getString(1, false, true)); // not initialized
}

ft.setExcludeSQliteOutputReport(true);
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_Parameters));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_UsePriceEscalation));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_NonrecurringCost));

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_VariableDictionary));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_SQLite));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_Table_SummaryReports));

auto objs = w.getObjectsByType(IddObjectType::OutputControl_Table_Style);
ASSERT_EQ(1, objs.size());
auto obj = objs[0];
EXPECT_EQ("HTML", obj.getString(0).get());
EXPECT_EQ("None", obj.getString(1, true).get()); // Return default
EXPECT_FALSE(obj.getString(1, false, true)); // not initialized
}

ft.setIPTabularOutput(true);
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_Parameters));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_UsePriceEscalation));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_NonrecurringCost));

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_VariableDictionary));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_SQLite));
EXPECT_EQ(1u, w.numObjectsOfType(IddObjectType::Output_Table_SummaryReports));

auto objs = w.getObjectsByType(IddObjectType::OutputControl_Table_Style);
ASSERT_EQ(1, objs.size());
auto obj = objs[0];
EXPECT_EQ("HTML", obj.getString(0).get());
EXPECT_EQ("InchPound", obj.getString(1, false, true).get());
}

ft.setExcludeHTMLOutputReport(true);
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_Parameters));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_UsePriceEscalation));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::LifeCycleCost_RecurringCosts));

EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_VariableDictionary));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_SQLite));
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::Output_Table_SummaryReports));

// This also turns off the OutputControl:Table:Style
EXPECT_EQ(0u, w.numObjectsOfType(IddObjectType::OutputControl_Table_Style));
}
}

0 comments on commit 65607ae

Please sign in to comment.