-
Notifications
You must be signed in to change notification settings - Fork 193
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
v24.1.0-IOFreeze: HeatExchangerAirToAirSensibleAndLatent #5099
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was tempted to say we shouldn't even try to support backward compat here (just log a message saying the method does nothing now and you should call xxxCurve() method), but it seems some amount of backward compat is needed due to the SDD stuff.
I think I'm going to sleep on it, I'll try to think overnight about the amount of work that'd be necessary to properly support it.
src/osversion/VersionTranslator.cpp
Outdated
m_new.push_back(varList); | ||
ss << varList; | ||
|
||
m_new.push_back(var); | ||
ss << var; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_new.push_back(varList); | |
ss << varList; | |
m_new.push_back(var); | |
ss << var; | |
ss << varList; | |
m_new.emplace_back(std::move(varList)); | |
ss << var; | |
m_new.emplace_back(std::move(var)); |
src/osversion/VersionTranslator.cpp
Outdated
m_refactored.push_back(RefactoredObjectData(object, newObject)); | ||
ss << newObject; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_refactored.push_back(RefactoredObjectData(object, newObject)); | |
ss << newObject; | |
ss << newObject; | |
m_refactored.emplace_back(object, std::move(newObject)); |
bool HeatExchangerAirToAirSensibleAndLatent_Impl::setSensibleEffectivenessat100CoolingAirFlow(double sensibleEffectivenessat100CoolingAirFlow) { | ||
// FIXME: wouldn't this value need to get set on the tablelookup if it exists? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. The 100% value is set, and then the Curve will express the relationship of the Effectiveness as a function of the cooling air flow. This is the same thing that's used for a eg for a Chiller: you set the COP at rated conditions, and the curve modifies based on it.
I guess remove all these FIXME
TableIndependentVariable var(model); | ||
var.setInterpolationMethod("Linear"); | ||
var.setExtrapolationMethod("Linear"); | ||
var.setMinimumValue(0.0); | ||
var.setMaximumValue(10.0); | ||
var.setUnitType("Dimensionless"); | ||
var.addValue(0.75); | ||
var.addValue(1.0); | ||
|
||
TableLookup s75heating(model); | ||
s75heating.setNormalizationMethod("DivisorOnly"); | ||
s75heating.setNormalizationDivisor(0.76); | ||
s75heating.setMinimumOutput(0.0); | ||
s75heating.setMaximumOutput(10.0); | ||
s75heating.setOutputUnitType("Dimensionless"); | ||
s75heating.addOutputValue(0.81); | ||
s75heating.addOutputValue(0.76); | ||
s75heating.addIndependentVariable(var); | ||
setSensibleEffectivenessofHeatingAirFlowCurve(s75heating); | ||
|
||
TableLookup l75heating(model); | ||
l75heating.setNormalizationMethod("DivisorOnly"); | ||
l75heating.setNormalizationDivisor(0.68); | ||
l75heating.setMinimumOutput(0.0); | ||
l75heating.setMaximumOutput(10.0); | ||
l75heating.setOutputUnitType("Dimensionless"); | ||
l75heating.addOutputValue(0.73); | ||
l75heating.addOutputValue(0.68); | ||
l75heating.addIndependentVariable(var); | ||
setLatentEffectivenessofHeatingAirFlowCurve(l75heating); | ||
|
||
TableLookup s75cooling(model); | ||
s75cooling.setNormalizationMethod("DivisorOnly"); | ||
s75cooling.setNormalizationDivisor(0.76); | ||
s75cooling.setMinimumOutput(0.0); | ||
s75cooling.setMaximumOutput(10.0); | ||
s75cooling.setOutputUnitType("Dimensionless"); | ||
s75cooling.addOutputValue(0.81); | ||
s75cooling.addOutputValue(0.76); | ||
s75cooling.addIndependentVariable(var); | ||
setSensibleEffectivenessofCoolingAirFlowCurve(s75cooling); | ||
|
||
TableLookup l75cooling(model); | ||
l75cooling.setNormalizationMethod("DivisorOnly"); | ||
l75cooling.setNormalizationDivisor(0.68); | ||
l75cooling.setMinimumOutput(0.0); | ||
l75cooling.setMaximumOutput(10.0); | ||
l75cooling.setOutputUnitType("Dimensionless"); | ||
l75cooling.addOutputValue(0.73); | ||
l75cooling.addOutputValue(0.68); | ||
l75cooling.addIndependentVariable(var); | ||
setLatentEffectivenessofCoolingAirFlowCurve(l75cooling); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so I get why this is here: to maintain the same effectiveness at different airflows as we had before.
- We could also not do this, similar to what E+ would do if you create this object in the IDF Editor
- Leave them empty so the effectiveness is linear.
- You could extract that bit of code into a public method, something like "applyDefaultEffectivenessCurves" or something for convenience, so that the user has the ability to use the former defaults with a single method call.
- VT (already done here) + modification of the OS resources ruby tests would ensure we don't show EUI deviations.
- If we want these curves to be set, then please name the Table / Vars
// DEPRECATED | ||
double HeatExchangerAirToAirSensibleAndLatent::sensibleEffectivenessat75HeatingAirFlow() const { | ||
DEPRECATED_AT_MSG(3, 8, 0, "As of EnergyPlus 24.1.0, this property ..."); | ||
if (boost::optional<TableLookup> sensibleEffectivenessofHeatingAirFlowCurve_ = | ||
sensibleEffectivenessofHeatingAirFlowCurve()->optionalCast<TableLookup>()) { | ||
return sensibleEffectivenessofHeatingAirFlowCurve_->outputValues()[0]; | ||
} else { | ||
return getImpl<detail::HeatExchangerAirToAirSensibleAndLatent_Impl>()->sensibleEffectivenessat100HeatingAirFlow(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
You have no proof that the
outputValues()[0]
corresponds to X=0.75. If I created that TableLookup manually, this may very well NOT be the case. -
You MUST check if the
sensibleEffectivenessofHeatingAirFlowCurve()
is initialized before you deference it or it'll throw if not. Your testing didn't catch it because the curves are optional BUT your constructor is initializing them. -
If I have set something other than a TableLookup (meaning a regular Curve:XXX object), you're also returning the 100 airflow without warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the getters would work fine if we had TableLookup_Impl::evaluate
, but we don't.
@@ -744,5 +804,196 @@ namespace model { | |||
return getImpl<detail::HeatExchangerAirToAirSensibleAndLatent_Impl>()->autosizedNominalSupplyAirFlowRate(); | |||
} | |||
|
|||
// DEPRECATED | |||
double HeatExchangerAirToAirSensibleAndLatent::sensibleEffectivenessat75HeatingAirFlow() const { | |||
DEPRECATED_AT_MSG(3, 8, 0, "As of EnergyPlus 24.1.0, this property ..."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: update the message.
DEPRECATED_AT_MSG(3, 8, 0, "Use sensibleEffectivenessofHeatingAirFlowCurve instead.");
} else if (!sensibleEffectivenessofHeatingAirFlowCurve()) { | ||
double sensibleEffectivenessat100HeatingAirFlow = | ||
getImpl<detail::HeatExchangerAirToAirSensibleAndLatent_Impl>()->sensibleEffectivenessat100HeatingAirFlow(); | ||
|
||
TableIndependentVariable var(model()); | ||
var.setInterpolationMethod("Linear"); | ||
var.setExtrapolationMethod("Linear"); | ||
var.setMinimumValue(0.0); | ||
var.setMaximumValue(10.0); | ||
var.setUnitType("Dimensionless"); | ||
var.addValue(0.75); | ||
var.addValue(1.0); | ||
|
||
TableLookup tableLookup(model()); | ||
tableLookup.setNormalizationMethod("DivisorOnly"); | ||
tableLookup.setNormalizationDivisor(sensibleEffectivenessat100HeatingAirFlow); | ||
tableLookup.setMinimumOutput(0.0); | ||
tableLookup.setMaximumOutput(10.0); | ||
tableLookup.setOutputUnitType("Dimensionless"); | ||
tableLookup.addOutputValue(sensibleEffectivenessat75HeatingAirFlow); | ||
tableLookup.addOutputValue(sensibleEffectivenessat100HeatingAirFlow); | ||
tableLookup.addIndependentVariable(var); | ||
|
||
return setSensibleEffectivenessofHeatingAirFlowCurve(tableLookup); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No ambiguity in this case: if the curve isnt there, we can make a table lookup indeed.
if (boost::optional<TableLookup> sensibleEffectivenessofHeatingAirFlowCurve_ = | ||
sensibleEffectivenessofHeatingAirFlowCurve()->optionalCast<TableLookup>()) { | ||
double sensibleEffectivenessat100HeatingAirFlow = | ||
getImpl<detail::HeatExchangerAirToAirSensibleAndLatent_Impl>()->sensibleEffectivenessat100HeatingAirFlow(); | ||
sensibleEffectivenessofHeatingAirFlowCurve_->setOutputValues( | ||
{sensibleEffectivenessat75HeatingAirFlow, sensibleEffectivenessat100HeatingAirFlow}); | ||
return setSensibleEffectivenessofHeatingAirFlowCurve(sensibleEffectivenessofHeatingAirFlowCurve_.get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same problems: can't dereference the curve object if not initialized, and the setting of the output values isn't good since you're not also modifying the independent variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note, but related to a potential final conclusion on whether we should try to maintain backward compatibilty: The TableLookup
interface is crap from a user experience perspective. The former TableMultiVariableLookup
was better in that sense since you could do addPoint(x, y)
and it'd detect if the x value was already there, and you could call boost::optional<double> yValue(const std::vector<double>& xValues)
I think we should re-add that capability...
src/sdd/MapHVAC.cpp
Outdated
if (boost::optional<model::Curve> curve_ = hx.sensibleEffectivenessofHeatingAirFlowCurve()) { | ||
if (boost::optional<model::TableLookup> sensibleEffectivenessofHeatingAirFlowCurve_ = curve_->optionalCast<TableLookup>()) { | ||
double sensibleEffectivenessat100HeatingAirFlow = hx.sensibleEffectivenessat100HeatingAirFlow(); | ||
sensibleEffectivenessofHeatingAirFlowCurve_->setOutputValues({_htgSensEff75.get(), sensibleEffectivenessat100HeatingAirFlow}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so it seems we do want to support some amount of backward compatibility in setting the 75% effectivness due to this MapHVAC stuff.
I don't think the current implementation here is good though. You're creating the object, so you're in control. You should create the curve instead of checking whether it exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the opposite way (OSM > SDD) is missing too.
Options:
|
3957197
to
3994d48
Compare
…sCurves` to opt-in to set the default table lookups
…the table object in RT (note: object isn't FT'ed so no op there)
3994d48
to
8c9e74e
Compare
CI Results for 8c9e74e:
|
@joseph-robertson I made some changes, this is good enough to go into the main IO freeze branch |
@joseph-robertson @jmarrec we may need to modify the work done in this PR. Some models made in OpenStudio are hitting a failure in EnergyPlus with the default curve set: NREL/EnergyPlus#10464 |
update - issue is the default table from OpenStudio has a divide by zero. Need to change the OpenStudio default. |
Pull request overview
Remove:
Add:
Questions:
Pull Request Author
src/model/test
)src/energyplus/Test
)src/osversion/VersionTranslator.cpp
)Labels:
IDDChange
APIChange
Pull Request - Ready for CI
so that CI builds your PRReview Checklist
This will not be exhaustively relevant to every PR.