Skip to content

Commit

Permalink
Merge pull request #4192 from NREL/issue-4182
Browse files Browse the repository at this point in the history
Addresses #4182, provide OS SDK/API support for the EnergyPlus "Generator:WindTurbine" object
  • Loading branch information
tijcolem authored Feb 5, 2021
2 parents 207d714 + 450951f commit 1de7dfe
Show file tree
Hide file tree
Showing 26 changed files with 2,090 additions and 102 deletions.
160 changes: 155 additions & 5 deletions resources/model/OpenStudio.idd
Original file line number Diff line number Diff line change
Expand Up @@ -29912,10 +29912,10 @@ OS:PhotovoltaicPerformance:EquivalentOne-Diode,
\minimum 0.0

OS:Generator:FuelCell,
\memo This generator model is the FC model from IEA Annex 42
\memo This generator model is the FC model from IEA Annex 42
A1, \field Handle
\type handle
\required-field
\type handle
\required-field
A2, \field Name
\required-field
\reference GeneratorNames
Expand Down Expand Up @@ -30348,8 +30348,8 @@ OS:Generator:FuelSupply,
\max-fields 38
\memo Used only with Generator:FuelCell and Generator:MicroCHP
A1, \field Handle
\type handle
\required-field
\type handle
\required-field
A2, \field Name
\required-field
\reference GenFuelSupNames
Expand Down Expand Up @@ -30405,6 +30405,156 @@ OS:Generator:FuelSupply,
\minimum 0.0
\maximum 1.0

OS:Generator:WindTurbine,
\memo Wind turbine generator.
\min-fields 27
A1, \field Handle
\type handle
\required-field
A2, \field Name
\required-field
\reference GeneratorNames
A3, \field Availability Schedule Name
\note Availability schedule name for this system. Schedule value > 0 means the system is available.
\note If this field is blank, the system is always available.
\type object-list
\object-list ScheduleNames
\required-field
A4, \field Rotor Type
\note allowed values are: Horizontal Axis Wind Turbine or Vertical Axis Wind Turbine
\type choice
\key HorizontalAxisWindTurbine
\key VerticalAxisWindTurbine
\required-field
A5, \field Power Control
\note Constant power output is obtained in the last three control types
\note when the wind speed exceeds the rated wind speed.
\note allowed values are: Fixed Speed Fixed Pitch, Fixed Speed Variable Pitch,
\note Variable Speed Fixed Pitch or Variable Speed Variable Pitch
\type choice
\key FixedSpeedFixedPitch
\key FixedSpeedVariablePitch
\key VariableSpeedFixedPitch
\key VariableSpeedVariablePitch
\required-field
N1, \field Rated Rotor Speed
\required-field
\type real
\minimum> 0.0
\units rev/min
N2, \field Rotor Diameter
\note This field is the diameter of the perpendicular circle of the Vertical Axis Wind Turbine system
\note from the upright pole on the ground.
\required-field
\type real
\minimum> 0.0
\units m
N3, \field Overall Height
\note This field is the height of the hub for the Horizontal Axis Wind Turbines and
\note of the pole for the Vertical Axis Wind Turbines.
\required-field
\type real
\minimum> 0.0
\units m
N4, \field Number of Blades
\minimum 2
\required-field
N5, \field Rated Power
\required-field
\note This field is the nominal power at the rated wind speed.
\note Users should input maximum power in case of Fixed Speed Fixed Pitch control type.
\type real
\minimum> 0.0
\units W
N6, \field Rated Wind Speed
\required-field
\type real
\minimum> 0.0
\units m/s
N7, \field Cut In Wind Speed
\required-field
\type real
\minimum> 0.0
\units m/s
N8, \field Cut Out Wind Speed
\required-field
\type real
\minimum> 0.0
\units m/s
N9, \field Fraction system Efficiency
\type real
\minimum> 0.0
\maximum 1.0
\required-field
N10,\field Maximum Tip Speed Ratio
\type real
\minimum> 0.0
\maximum 12.0
\required-field
N11,\field Maximum Power Coefficient
\note This field should be input if the rotor type is Horizontal Axis Wind Turbine
\type real
\minimum> 0.0
\maximum 0.59
\required-field
N12,\field Annual Local Average Wind Speed
\type real
\units m/s
\minimum> 0.0
N13,\field Height for Local Average Wind Speed
\type real
\units m
\minimum> 0.0
\required-field
N14,\field Blade Chord Area
\type real
\units m2
\required-field
\minimum 0.0
N15,\field Blade Drag Coefficient
\note This field is only for Vertical Axis Wind Turbine..
\note The user must input this field if the rotor type is Vertical Axis Wind Turbine.
\type real
\required-field
\minimum 0.0
N16,\field Blade Lift Coefficient
\note This field is only for Vertical Axis Wind Turbine..
\note The user must input this field if the rotor type is Vertical Axis Wind Turbine.
\type real
\required-field
\minimum 0.0
N17,\field Power Coefficient C1
\note This field is only available for Horizontal Axis Wind Turbine.
\note The user should input all six parameters
\note so that the analytic approximation is assumed.
\note The simple approximation will be assumed,
\note if any field C1 through C6 is not input.
\note Leave this field blank, if the manufacturer's data is unavailable
\note so that the simple approximation will be assumed.
\minimum> 0.0
\type real
\required-field
N18,\field Power Coefficient C2
\minimum> 0.0
\type real
\required-field
N19,\field Power Coefficient C3
\minimum> 0.0
\type real
\required-field
N20,\field Power Coefficient C4
\minimum 0.0
\type real
\required-field
N21,\field Power Coefficient C5
\minimum> 0.0
\type real
\required-field
N22;\field Power Coefficient C6
\minimum> 0.0
\type real
\required-field

OS:Generator:PVWatts,
\min-fields 4
\memo Describes a simple set of inputs for an array of photovoltaic (PV) modules as described
Expand Down
3 changes: 3 additions & 0 deletions src/energyplus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ set(${target_name}_src
ForwardTranslator/ForwardTranslateGeneratorFuelCellStackCooler.cpp
ForwardTranslator/ForwardTranslateGeneratorFuelCellWaterSupply.cpp
ForwardTranslator/ForwardTranslateGeneratorFuelSupply.cpp
ForwardTranslator/ForwardTranslateGeneratorWindTurbine.cpp
ForwardTranslator/ForwardTranslateGroundHeatExchangerHorizontalTrench.cpp
ForwardTranslator/ForwardTranslateGroundHeatExchangerVertical.cpp
ForwardTranslator/ForwardTranslateHeaderedPumpsConstantSpeed.cpp
Expand Down Expand Up @@ -479,6 +480,7 @@ set(${target_name}_src
ReverseTranslator/ReverseTranslateFoundationKivaSettings.cpp
ReverseTranslator/ReverseTranslateGasEquipment.cpp
ReverseTranslator/ReverseTranslateGeneratorMicroTurbine.cpp
ReverseTranslator/ReverseTranslateGeneratorWindTurbine.cpp
ReverseTranslator/ReverseTranslateHeatBalanceAlgorithm.cpp
ReverseTranslator/ReverseTranslateHotWaterEquipment.cpp
ReverseTranslator/ReverseTranslateInternalMass.cpp
Expand Down Expand Up @@ -631,6 +633,7 @@ set(${target_name}_test_src
Test/FuelCell_GTest.cpp
Test/GasEquipment_GTest.cpp
Test/GeneratorMicroTurbine_GTest.cpp
Test/GeneratorWindTurbine_GTest.cpp
Test/HeatPumpWaterToWaterEquationFit_GTest.cpp
Test/HotWaterEquipment_GTest.cpp
Test/IlluminanceMap_GTest.cpp
Expand Down
101 changes: 21 additions & 80 deletions src/energyplus/ForwardTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,75 +358,6 @@ namespace energyplus {
}
}

// remove orphan Generator:MicroTurbine
for (auto& chp : model.getConcreteModelObjects<GeneratorMicroTurbine>()) {
if (!chp.electricLoadCenterDistribution()) {
LOG(Warn,
"GeneratorMicroTurbine " << chp.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
chp.remove();
continue;
}
}

// remove orphan photovoltaics
for (auto& pv : model.getConcreteModelObjects<GeneratorPhotovoltaic>()) {
if (!pv.electricLoadCenterDistribution()) {
LOG(Warn,
"GeneratorPhotovoltaic " << pv.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
pv.remove();
continue;
}
if (!pv.surface()) {
LOG(Warn, "GeneratorPhotovoltaic " << pv.name().get() << " is not referenced by any surface, it will not be translated.");
pv.remove();
}
}

// remove orphan Generator:PVWatts
for (auto& pv : model.getConcreteModelObjects<GeneratorPVWatts>()) {
if (!pv.electricLoadCenterDistribution()) {
LOG(Warn, "GeneratorPVWatts " << pv.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
pv.remove();
continue;
}
}

// remove orphan Generator:FuelCell
for (auto& fc : model.getConcreteModelObjects<GeneratorFuelCell>()) {
if (!fc.electricLoadCenterDistribution()) {
//get the HX from the FC since that is the parent and remove it, thus removing the FC
LOG(Warn, "GeneratorFuelCell " << fc.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
fc.heatExchanger().remove();
//fc.remove();
continue;
}
}

// Remove orphan Storage
for (auto& storage : model.getModelObjects<ElectricalStorage>()) {
if (!storage.electricLoadCenterDistribution()) {
LOG(Warn,
"Electrical Storage " << storage.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
storage.remove();
}
}

// Remove orphan Converters
for (auto& converter : model.getConcreteModelObjects<ElectricLoadCenterStorageConverter>()) {
if (!converter.electricLoadCenterDistribution()) {
LOG(Warn, "Converter " << converter.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
converter.remove();
}
}

// Remove orphan Inverters
for (auto& inverter : model.getModelObjects<Inverter>()) {
if (!inverter.electricLoadCenterDistribution()) {
LOG(Warn, "Inverter " << inverter.name().get() << " is not referenced by any ElectricLoadCenterDistribution, it will not be translated.");
inverter.remove();
}
}

// TODO: Is this still needed?
// ensure shading controls only reference windows in a single zone and determine control sequence number
// DLM: ideally E+ would not need to know the zone, shading controls could work across zones
Expand Down Expand Up @@ -1794,6 +1725,11 @@ namespace energyplus {
retVal = translateGeneratorPVWatts(temp);
break;
}
case openstudio::IddObjectType::OS_Generator_WindTurbine: {
model::GeneratorWindTurbine temp = modelObject.cast<GeneratorWindTurbine>();
retVal = translateGeneratorWindTurbine(temp);
break;
}
case openstudio::IddObjectType::OS_Glare_Sensor: {
// no-op
break;
Expand Down Expand Up @@ -3233,8 +3169,12 @@ namespace energyplus {
result.push_back(IddObjectType::OS_Refrigeration_TranscriticalSystem);

result.push_back(IddObjectType::OS_ElectricLoadCenter_Distribution);
result.push_back(IddObjectType::OS_Generator_MicroTurbine);
result.push_back(IddObjectType::OS_Generator_FuelCell);
// ElectricLoadCenterDistribution is responsible for translating its generators/inverters/storages
// result.push_back(IddObjectType::OS_Generator_MicroTurbine);
// result.push_back(IddObjectType::OS_Generator_FuelCell);
// result.push_back(IddObjectType::OS_Generator_Photovoltaic);
// result.push_back(IddObjectType::OS_Generator_PVWatts);
// result.push_back(IddObjectType::OS_Generator_WindTurbine);
// Fuel Cell is responsible for translating these
// result.push_back(IddObjectType::OS_Generator_FuelCell_AirSupply);
// result.push_back(IddObjectType::OS_Generator_FuelCell_AuxiliaryHeater);
Expand All @@ -3246,16 +3186,17 @@ namespace energyplus {
// result.push_back(IddObjectType::OS_Generator_FuelCell_WaterSupply);
// Fuel Cell (and MicroCHP when implemented) are responsible for translating this one
// result.push_back(IddObjectType::OS_Generator_FuelSupply);
// result.push_back(IddObjectType::OS_ElectricLoadCenter_Inverter_LookUpTable);
// result.push_back(IddObjectType::OS_ElectricLoadCenter_Inverter_Simple);
// result.push_back(IddObjectType::OS_ElectricLoadCenter_Inverter_PVWatts);
// result.push_back(IddObjectType::OS_ElectricLoadCenter_Storage_Simple);
// result.push_back(IddObjectType::OS_ElectricLoadCenter_Storage_Converter);

// Generator_Photovoltaic is responsible for translating these two
// result.push_back(IddObjectType::OS_PhotovoltaicPerformance_EquivalentOneDiode);
// result.push_back(IddObjectType::OS_PhotovoltaicPerformance_Simple);

result.push_back(IddObjectType::OS_Generator_Photovoltaic);
result.push_back(IddObjectType::OS_Generator_PVWatts);
result.push_back(IddObjectType::OS_PhotovoltaicPerformance_EquivalentOneDiode);
result.push_back(IddObjectType::OS_PhotovoltaicPerformance_Simple);
result.push_back(IddObjectType::OS_ElectricLoadCenter_Inverter_LookUpTable);
result.push_back(IddObjectType::OS_ElectricLoadCenter_Inverter_Simple);
result.push_back(IddObjectType::OS_ElectricLoadCenter_Inverter_PVWatts);
result.push_back(IddObjectType::OS_ElectricLoadCenter_Storage_Simple);
result.push_back(IddObjectType::OS_ElectricLoadCenter_Storage_Converter);
// Transformer can be standalone, see ASHRAE9012016_OfficeMedium_Denver.idf for example
result.push_back(IddObjectType::OS_ElectricLoadCenter_Transformer);

// put these down here so they have a chance to be translated with their "parent"
Expand Down
3 changes: 3 additions & 0 deletions src/energyplus/ForwardTranslator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ namespace model {
class GeneratorFuelSupply;
class GeneratorPhotovoltaic;
class GeneratorPVWatts;
class GeneratorWindTurbine;
class GroundHeatExchangerHorizontalTrench;
class GroundHeatExchangerVertical;
class HeaderedPumpsConstantSpeed;
Expand Down Expand Up @@ -981,6 +982,8 @@ namespace energyplus {

boost::optional<IdfObject> translateGeneratorPVWatts(model::GeneratorPVWatts& modelObject);

boost::optional<IdfObject> translateGeneratorWindTurbine(model::GeneratorWindTurbine& modelObject);

boost::optional<IdfObject> translateGroundHeatExchangerHorizontalTrench(model::GroundHeatExchangerHorizontalTrench& modelObject);

boost::optional<IdfObject> translateGroundHeatExchangerVertical(model::GroundHeatExchangerVertical& modelObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,22 @@ namespace openstudio {
namespace energyplus {

boost::optional<IdfObject> ForwardTranslator::translateGeneratorPhotovoltaic(model::GeneratorPhotovoltaic& modelObject) {
IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::Generator_Photovoltaic, modelObject);

// We are going to check for required properties such as Surface before we register the object
// IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::Generator_Photovoltaic, modelObject);
IdfObject idfObject(openstudio::IddObjectType::Generator_Photovoltaic);
// Name
idfObject.setName(modelObject.nameString());

PhotovoltaicPerformance performance = modelObject.photovoltaicPerformance();
boost::optional<IdfObject> performanceIdf = translateAndMapModelObject(performance);
if (performanceIdf) {
idfObject.setString(Generator_PhotovoltaicFields::PhotovoltaicPerformanceObjectType, performanceIdf->iddObject().name());
idfObject.setString(Generator_PhotovoltaicFields::ModulePerformanceName, performanceIdf->name().get());
} else {
LOG(Warn, "Generator:Photovoltaic '" << idfObject.name().get() << "' missing required field 'Module Performance Name'")
LOG(Error,
"Generator:Photovoltaic '" << idfObject.name().get() << "' missing required field 'Module Performance Name', it will not be translated.");
return boost::none;
}

boost::optional<PlanarSurface> surface = modelObject.surface();
Expand All @@ -69,9 +76,13 @@ namespace energyplus {
}
}
if (!hasSurface) {
LOG(Warn, "Generator:Photovoltaic '" << idfObject.name().get() << "' missing required field 'Surface Name'")
LOG(Error, "Generator:Photovoltaic '" << idfObject.name().get() << "' missing required field 'Surface Name', it will not be translated.");
return boost::none;
}

// at this point, we can register the new object
m_idfObjects.push_back(idfObject);

idfObject.setString(Generator_PhotovoltaicFields::HeatTransferIntegrationMode, modelObject.heatTransferIntegrationMode());

idfObject.setDouble(Generator_PhotovoltaicFields::NumberofSeriesStringsinParallel, modelObject.numberOfModulesInParallel());
Expand Down
Loading

0 comments on commit 1de7dfe

Please sign in to comment.